"""Technique query service — framework-agnostic queries for technique details.""" # Enable future language features for compatibility from __future__ import annotations # Import Session, joinedload from sqlalchemy.orm from sqlalchemy.orm import Session, joinedload # Import EntityNotFoundError from app.domain.errors from app.domain.errors import EntityNotFoundError # Import Technique from app.models.technique from app.models.technique import Technique # Import get_defenses_for_technique from app.services.d3fend_import_service from app.services.d3fend_import_service import get_defenses_for_technique # Define function get_technique_detail def get_technique_detail(db: Session, mitre_id: str) -> dict: """Fetch full technique details including tests and D3FEND defenses.""" # Assign technique = ( technique = ( db.query(Technique) # Chain .options() call .options(joinedload(Technique.tests)) # Chain .filter() call .filter(Technique.mitre_id == mitre_id) # Chain .first() call .first() ) # Check: technique is None if technique is None: # Raise EntityNotFoundError raise EntityNotFoundError("Technique", mitre_id) # Assign defenses = get_defenses_for_technique(db, technique.id) defenses = get_defenses_for_technique(db, technique.id) # Return { return { # Literal argument value "id": str(technique.id), # Literal argument value "mitre_id": technique.mitre_id, # Literal argument value "name": technique.name, # Literal argument value "description": technique.description, # Literal argument value "tactic": technique.tactic, # Literal argument value "platforms": technique.platforms or [], # Literal argument value "mitre_version": technique.mitre_version, # Literal argument value "mitre_last_modified": technique.mitre_last_modified, # Literal argument value "is_subtechnique": technique.is_subtechnique, # Literal argument value "parent_mitre_id": technique.parent_mitre_id, # Literal argument value "status_global": technique.status_global.value if technique.status_global else "not_evaluated", # Literal argument value "review_required": technique.review_required, # Literal argument value "last_review_date": technique.last_review_date, # Literal argument value "tests": [ { # Literal argument value "id": str(t.id), # Literal argument value "name": t.name, # Literal argument value "state": t.state.value if t.state else None, # Literal argument value "result": t.result.value if t.result else None, # Literal argument value "platform": t.platform, # Literal argument value "created_at": t.created_at.isoformat() if t.created_at else None, } for t in technique.tests ], # Literal argument value "d3fend_defenses": defenses, }