fix(backend): sprint 3 post-review — nullable migration + dead code + tactic names
- Migration 0003: enforce techniques NOT NULL via batch_alter_table - Migration 0003: remove unused _sims table proxy and dead column/table imports - mitre.py: add _TACTIC_NAMES dict to fix 'Command And Control' → 'Command and Control'
This commit is contained in:
@@ -26,6 +26,21 @@ _TACTIC_ORDER = [
|
|||||||
"impact",
|
"impact",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_TACTIC_NAMES: dict[str, str] = {
|
||||||
|
"initial-access": "Initial Access",
|
||||||
|
"execution": "Execution",
|
||||||
|
"persistence": "Persistence",
|
||||||
|
"privilege-escalation": "Privilege Escalation",
|
||||||
|
"defense-evasion": "Defense Evasion",
|
||||||
|
"credential-access": "Credential Access",
|
||||||
|
"discovery": "Discovery",
|
||||||
|
"lateral-movement": "Lateral Movement",
|
||||||
|
"collection": "Collection",
|
||||||
|
"command-and-control": "Command and Control",
|
||||||
|
"exfiltration": "Exfiltration",
|
||||||
|
"impact": "Impact",
|
||||||
|
}
|
||||||
|
|
||||||
mitre_loaded: bool = False
|
mitre_loaded: bool = False
|
||||||
_index: list[dict[str, Any]] = []
|
_index: list[dict[str, Any]] = []
|
||||||
_tactics_by_technique: dict[str, list[str]] = {}
|
_tactics_by_technique: dict[str, list[str]] = {}
|
||||||
@@ -87,7 +102,7 @@ def _build_matrix(entries: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|||||||
techs = tactic_techs.get(tactic_id, [])
|
techs = tactic_techs.get(tactic_id, [])
|
||||||
# Sort techniques alphabetically.
|
# Sort techniques alphabetically.
|
||||||
techs_sorted = sorted(techs, key=lambda x: x["name"])
|
techs_sorted = sorted(techs, key=lambda x: x["name"])
|
||||||
tactic_name = tactic_id.replace("-", " ").title()
|
tactic_name = _TACTIC_NAMES.get(tactic_id, tactic_id.replace("-", " ").title())
|
||||||
matrix.append(
|
matrix.append(
|
||||||
{
|
{
|
||||||
"tactic_id": tactic_id,
|
"tactic_id": tactic_id,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import json
|
|||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.sql import column, table, text
|
from sqlalchemy.sql import text
|
||||||
|
|
||||||
|
|
||||||
revision = "0003"
|
revision = "0003"
|
||||||
@@ -16,15 +16,6 @@ down_revision = "0002"
|
|||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
# Lightweight table proxies for data migration (no ORM import).
|
|
||||||
_sims = table(
|
|
||||||
"simulations",
|
|
||||||
column("id", sa.Integer),
|
|
||||||
column("mitre_technique_id", sa.String),
|
|
||||||
column("mitre_technique_name", sa.String),
|
|
||||||
column("techniques", sa.Text),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
bind = op.get_bind()
|
bind = op.get_bind()
|
||||||
@@ -47,8 +38,8 @@ def upgrade():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 3. Make NOT NULL now that every row has a value.
|
# 3. Make NOT NULL now that every row has a value.
|
||||||
# SQLite doesn't support ALTER COLUMN, so we skip the nullable constraint
|
with op.batch_alter_table("simulations") as batch_op:
|
||||||
# change at DDL level — the application model enforces it.
|
batch_op.alter_column("techniques", existing_type=sa.Text(), nullable=False)
|
||||||
|
|
||||||
# 4. Drop old scalar columns.
|
# 4. Drop old scalar columns.
|
||||||
with op.batch_alter_table("simulations") as batch_op:
|
with op.batch_alter_table("simulations") as batch_op:
|
||||||
|
|||||||
Reference in New Issue
Block a user