feat: add autonomous fiscal control panel

This commit is contained in:
gti
2026-09-22 15:36:12 -03:00
parent 636ed5228b
commit 301aac112e
34 changed files with 1252 additions and 9 deletions
+8 -1
View File
@@ -4,6 +4,10 @@ from central.app.models import Base
from central.app.config import settings
config = context.config
target_metadata = Base.metadata
def run_migrations_offline():
context.configure(url=settings.database_url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"})
with context.begin_transaction():
context.run_migrations()
def run_migrations_online():
config.set_main_option("sqlalchemy.url", settings.database_url)
engine = engine_from_config(config.get_section(config.config_ini_section), prefix="sqlalchemy.", poolclass=pool.NullPool)
@@ -11,4 +15,7 @@ def run_migrations_online():
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
run_migrations_online()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
@@ -5,7 +5,7 @@ import sqlalchemy as sa
revision = "0015_ai_budget_and_product_cache"
down_revision = "0014_ai_eval_cache"
down_revision = "0014"
branch_labels = None
depends_on = None
@@ -0,0 +1,101 @@
"""Add the operational control-plane records."""
from alembic import op
import sqlalchemy as sa
revision = "0017_control_plane_foundation"
down_revision = "0016_blocked_product_registry"
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
"installations",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("agent_id", sa.Integer(), sa.ForeignKey("agents.id"), nullable=False),
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id"), nullable=False),
sa.Column("installation_id", sa.String(36), nullable=False),
sa.Column("display_name", sa.String(160), nullable=False, server_default=""),
sa.Column("customer_code", sa.String(64)), sa.Column("notes", sa.Text()),
sa.Column("hostname", sa.String(255)), sa.Column("windows_version", sa.String(128)),
sa.Column("machine_fingerprint", sa.String(128)), sa.Column("company_code", sa.String(64)),
sa.Column("company_name", sa.String(160)), sa.Column("company_cnpj_masked", sa.String(24)),
sa.Column("company_uf", sa.String(2)), sa.Column("company_crt", sa.String(16)),
sa.Column("firebird_version", sa.String(64)), sa.Column("firebird_ods", sa.String(32)),
sa.Column("database_identifier", sa.String(255)), sa.Column("capabilities", sa.JSON(), nullable=False, server_default="{}"),
sa.Column("fiscal_engine_version", sa.String(64)), sa.Column("dataset_versions", sa.JSON(), nullable=False, server_default="{}"),
sa.Column("started_at", sa.DateTime(timezone=True)), sa.Column("last_seen_at", sa.DateTime(timezone=True)),
sa.Column("last_status", sa.String(32)), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.UniqueConstraint("installation_id", name="uq_installation_identity"),
sa.UniqueConstraint("agent_id", name="uq_installation_agent"),
)
op.create_index("ix_installations_agent_id", "installations", ["agent_id"])
op.create_index("ix_installations_tenant_id", "installations", ["tenant_id"])
op.create_index("ix_installations_hostname", "installations", ["hostname"])
op.create_index("ix_installations_customer_code", "installations", ["customer_code"])
op.create_index("ix_installations_last_seen_at", "installations", ["last_seen_at"])
op.create_index("ix_installations_installation_id", "installations", ["installation_id"])
op.create_table(
"agent_snapshots",
sa.Column("id", sa.Integer(), primary_key=True), sa.Column("installation_id", sa.Integer(), sa.ForeignKey("installations.id"), nullable=False),
sa.Column("total_products", sa.Integer(), nullable=False, server_default="0"), sa.Column("fiscally_complete", sa.Integer(), nullable=False, server_default="0"),
sa.Column("safe_blocked", sa.Integer(), nullable=False, server_default="0"), sa.Column("failed_products", sa.Integer(), nullable=False, server_default="0"),
sa.Column("coverage_percent", sa.Float(), nullable=False, server_default="0"), sa.Column("blockers", sa.JSON(), nullable=False, server_default="{}"),
sa.Column("last_job_status", sa.String(16)), sa.Column("last_job_at", sa.DateTime(timezone=True)), sa.Column("last_successful_job_at", sa.DateTime(timezone=True)),
sa.Column("agent_health", sa.String(16), nullable=False, server_default="UNKNOWN"), sa.Column("health_reason", sa.Text()),
sa.Column("version_drift", sa.String(16), nullable=False, server_default="UNKNOWN"), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.UniqueConstraint("installation_id", name="uq_agent_snapshot_installation"),
)
for name, column in (("installation", "installation_id"), ("health", "agent_health"), ("version_drift", "version_drift"), ("updated", "updated_at")):
op.create_index(f"ix_agent_snapshots_{name}", "agent_snapshots", [column])
op.create_table(
"agent_events",
sa.Column("id", sa.Integer(), primary_key=True), sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id"), nullable=False),
sa.Column("installation_id", sa.Integer(), sa.ForeignKey("installations.id"), nullable=False), sa.Column("agent_id", sa.Integer(), sa.ForeignKey("agents.id"), nullable=False),
sa.Column("severity", sa.String(16), nullable=False), sa.Column("event_type", sa.String(48), nullable=False), sa.Column("message", sa.Text(), nullable=False),
sa.Column("structured_context", sa.JSON(), nullable=False, server_default="{}"), sa.Column("job_id", sa.Integer(), sa.ForeignKey("jobs.id")),
sa.Column("product_code", sa.String(64)), sa.Column("blocker_id", sa.Integer(), sa.ForeignKey("blocked_products.id")), sa.Column("is_audit", sa.Boolean(), nullable=False, server_default="false"),
sa.Column("occurred_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
)
for name, column in (("tenant", "tenant_id"), ("installation", "installation_id"), ("agent", "agent_id"), ("severity", "severity"), ("event_type", "event_type"), ("job", "job_id"), ("product", "product_code"), ("blocker", "blocker_id"), ("audit", "is_audit"), ("occurred", "occurred_at")):
op.create_index(f"ix_agent_events_{name}", "agent_events", [column])
op.create_table(
"admin_users",
sa.Column("id", sa.Integer(), primary_key=True), sa.Column("username", sa.String(128), nullable=False, unique=True),
sa.Column("password_hash", sa.String(255), nullable=False), sa.Column("is_active", sa.Boolean(), nullable=False, server_default="true"),
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()), sa.Column("last_login_at", sa.DateTime(timezone=True)),
)
op.create_index("ix_admin_users_username", "admin_users", ["username"])
op.create_table(
"web_sessions",
sa.Column("id", sa.Integer(), primary_key=True), sa.Column("admin_user_id", sa.Integer(), sa.ForeignKey("admin_users.id"), nullable=False),
sa.Column("token_hash", sa.String(64), nullable=False, unique=True), sa.Column("csrf_hash", sa.String(64), nullable=False),
sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.Column("last_seen_at", sa.DateTime(timezone=True), server_default=sa.func.now()), sa.Column("user_agent", sa.String(512)), sa.Column("remote_addr", sa.String(64)),
)
op.create_index("ix_web_sessions_admin_user_id", "web_sessions", ["admin_user_id"])
op.create_index("ix_web_sessions_token_hash", "web_sessions", ["token_hash"])
op.create_index("ix_web_sessions_expires_at", "web_sessions", ["expires_at"])
op.create_table(
"audit_events",
sa.Column("id", sa.Integer(), primary_key=True), sa.Column("admin_user_id", sa.Integer(), sa.ForeignKey("admin_users.id")),
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id")), sa.Column("action", sa.String(64), nullable=False),
sa.Column("target_type", sa.String(64), nullable=False), sa.Column("target_id", sa.String(128), nullable=False), sa.Column("context", sa.JSON(), nullable=False, server_default="{}"),
sa.Column("severity", sa.String(16), nullable=False, server_default="INFO"), sa.Column("occurred_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
)
for name, column in (("admin", "admin_user_id"), ("tenant", "tenant_id"), ("action", "action"), ("occurred", "occurred_at")):
op.create_index(f"ix_audit_events_{name}", "audit_events", [column])
def downgrade():
op.drop_table("audit_events")
op.drop_table("web_sessions")
op.drop_table("admin_users")
op.drop_table("agent_events")
op.drop_table("agent_snapshots")
op.drop_table("installations")