"""Deterministic in-memory C2 adapter — used when MIMIC_C2_ADAPTER=fake. Intended for integration tests and local development without a live Mythic instance. """ from __future__ import annotations from backend.app.services.c2.adapter import ( C2Adapter, C2Callback, C2Health, C2TaskPage, C2TaskStatus, ) _FAKE_CALLBACKS = [ C2Callback( display_id=1, active=True, host="WORKSTATION-01", user="jdoe", domain="LAB", last_checkin="2026-06-10T00:00:00Z", ), ] _FAKE_TASKS: dict[int, dict] = {} _next_task_id = 100 class FakeAdapter(C2Adapter): """In-memory adapter with deterministic behaviour.""" def test_connection(self) -> C2Health: return C2Health(ok=True) def list_callbacks(self) -> list[C2Callback]: return list(_FAKE_CALLBACKS) def create_task( self, callback_display_id: int, command: str, params: str | None = None, ) -> int: global _next_task_id tid = _next_task_id _next_task_id += 1 _FAKE_TASKS[tid] = { "display_id": tid, "callback_display_id": callback_display_id, "command": command, "params": params, "status": "submitted", "completed": False, "output": None, } return tid def get_task(self, task_display_id: int) -> C2TaskStatus: task = _FAKE_TASKS.get(task_display_id) if task is None: return C2TaskStatus(display_id=task_display_id, status="unknown", completed=False) return C2TaskStatus( display_id=task_display_id, status=task["status"], completed=task["completed"], ) def get_task_output(self, task_display_id: int) -> str: task = _FAKE_TASKS.get(task_display_id) if task is None: return "" return task.get("output") or "" def list_callback_tasks( self, callback_display_id: int, page: int = 1, page_size: int = 25, ) -> C2TaskPage: items = [ t for t in _FAKE_TASKS.values() if t["callback_display_id"] == callback_display_id ] start = (page - 1) * page_size return C2TaskPage( items=items[start : start + page_size], total=len(items), page=page, page_size=page_size, )