Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 34 additions & 138 deletions kernel_ai/api/rest.py
Original file line number Diff line number Diff line change
@@ -1,142 +1,38 @@
"""
REST API under ``/api``. Implementations are in ``kernel_ai.webapp`` (lazy import).
"""
"""REST API under ``/api``."""
from flask import Blueprint
from kernel_ai.http import api as h

bp = Blueprint("api", __name__, url_prefix="/api")


def _core():
from kernel_ai import webapp as core

return core


@bp.route("/syscalls-realtime")
def syscalls_realtime():
return _core().syscalls_realtime()


@bp.route("/kernel-data")
def kernel_data():
return _core().kernel_data()


@bp.route("/process-kernel-map")
def process_kernel_map():
return _core().process_kernel_map()


@bp.route("/processes")
def get_processes():
return _core().get_processes()


@bp.route("/nginx-files")
def nginx_files():
return _core().nginx_files()


@bp.route("/active-connections")
def active_connections():
return _core().active_connections()


@bp.route("/traceroute")
def traceroute_info():
return _core().traceroute_info()


@bp.route("/network-stack-realtime")
def network_stack_realtime():
return _core().network_stack_realtime()


@bp.route("/devices-realtime")
def devices_realtime():
return _core().devices_realtime()


@bp.route("/filesystem-blocks")
def filesystem_blocks():
return _core().filesystem_blocks()


@bp.route("/isolation-context")
def isolation_context():
return _core().isolation_context()


@bp.route("/process/<int:pid>/threads")
def get_process_threads(pid):
return _core().get_process_threads(pid)


@bp.route("/process/<int:pid>/cpu")
def get_process_cpu(pid):
return _core().get_process_cpu(pid)


@bp.route("/process/<int:pid>/fds")
def get_process_fds(pid):
return _core().get_process_fds(pid)


@bp.route("/processes-detailed")
def get_processes_detailed():
return _core().get_processes_detailed()


@bp.route("/ipc-links")
def get_ipc_links():
return _core().get_ipc_links()


@bp.route("/proc-matrix")
def get_proc_matrix():
return _core().get_proc_matrix()


@bp.route("/proc-timeline")
def get_proc_timeline():
return _core().get_proc_timeline()


@bp.route("/execution-context")
def get_execution_context():
return _core().get_execution_context()


@bp.route("/kernel-dna")
def kernel_dna():
return _core().kernel_dna()


@bp.route("/crypto-realtime")
def crypto_realtime():
return _core().crypto_realtime()


@bp.route("/security-realtime")
def security_realtime():
return _core().security_realtime()


@bp.route("/processes-realtime")
def processes_realtime():
return _core().processes_realtime()


@bp.route("/frontend-logs", methods=["POST", "OPTIONS"])
def ingest_frontend_logs():
return _core().ingest_frontend_logs()


@bp.route("/proc-graph")
def proc_graph():
return _core().get_proc_graph()


@bp.route("/process-files")
def process_files():
return _core().get_process_files()
_API_ROUTES = [
("/syscalls-realtime", "syscalls_realtime", h.syscalls_realtime, None),
("/kernel-data", "kernel_data", h.kernel_data, None),
("/process-kernel-map", "process_kernel_map", h.process_kernel_map, None),
("/processes", "get_processes", h.get_processes, None),
("/nginx-files", "nginx_files", h.nginx_files, None),
("/active-connections", "active_connections", h.active_connections, None),
("/traceroute", "traceroute_info", h.traceroute_info, None),
("/network-stack-realtime", "network_stack_realtime", h.network_stack_realtime, None),
("/devices-realtime", "devices_realtime", h.devices_realtime, None),
("/filesystem-blocks", "filesystem_blocks", h.filesystem_blocks, None),
("/isolation-context", "isolation_context", h.isolation_context, None),
("/process/<int:pid>/threads", "get_process_threads", h.get_process_threads, None),
("/process/<int:pid>/cpu", "get_process_cpu", h.get_process_cpu, None),
("/process/<int:pid>/fds", "get_process_fds", h.get_process_fds, None),
("/processes-detailed", "get_processes_detailed", h.get_processes_detailed, None),
("/ipc-links", "get_ipc_links", h.get_ipc_links, None),
("/proc-matrix", "get_proc_matrix", h.get_proc_matrix, None),
("/proc-timeline", "get_proc_timeline", h.get_proc_timeline, None),
("/execution-context", "get_execution_context", h.get_execution_context, None),
("/kernel-dna", "kernel_dna", h.kernel_dna, None),
("/crypto-realtime", "crypto_realtime", h.crypto_realtime, None),
("/security-realtime", "security_realtime", h.security_realtime, None),
("/processes-realtime", "processes_realtime", h.processes_realtime, None),
("/frontend-logs", "ingest_frontend_logs", h.ingest_frontend_logs, ["POST", "OPTIONS"]),
("/proc-graph", "proc_graph", h.get_proc_graph, None),
("/process-files", "process_files", h.get_process_files, None),
]

for rule, endpoint, view_func, methods in _API_ROUTES:
kwargs = {"methods": methods} if methods else {}
bp.add_url_rule(rule, endpoint=endpoint, view_func=view_func, **kwargs)
55 changes: 55 additions & 0 deletions kernel_ai/contracts/api_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,32 @@ class FilesystemBlocksResponse(TypedDict):
meta: dict


class ProcessesRealtimeResponse(TypedDict):
timestamp: str
syscalls_interception: list
network_tracing: list
security_hooks: list
neural_graph: dict
memory_visual: dict
meta: dict


class ExecutionContextResponse(TypedDict):
mode: str
cpu_state: str
syscall_active: bool
interrupts: list
irq_stack: dict
timestamp: str


class KernelDNAResponse(TypedDict):
nucleotides: list
genes: list
mutations: list
timestamp: str


def _expect_dict(payload: Any, name: str) -> dict:
if not isinstance(payload, dict):
raise ValueError(f"{name} must be a JSON object")
Expand Down Expand Up @@ -106,3 +132,32 @@ def validate_filesystem_blocks_response(payload: Any) -> None:
_expect_key(data, "zones", list, "filesystem_blocks")
_expect_key(data, "blocks", list, "filesystem_blocks")
_expect_key(data, "meta", dict, "filesystem_blocks")


def validate_processes_realtime_response(payload: Any) -> None:
data = _expect_dict(payload, "processes_realtime")
_expect_key(data, "timestamp", str, "processes_realtime")
_expect_key(data, "syscalls_interception", list, "processes_realtime")
_expect_key(data, "network_tracing", list, "processes_realtime")
_expect_key(data, "security_hooks", list, "processes_realtime")
_expect_key(data, "neural_graph", dict, "processes_realtime")
_expect_key(data, "memory_visual", dict, "processes_realtime")
_expect_key(data, "meta", dict, "processes_realtime")


def validate_execution_context_response(payload: Any) -> None:
data = _expect_dict(payload, "execution_context")
_expect_key(data, "mode", str, "execution_context")
_expect_key(data, "cpu_state", str, "execution_context")
_expect_key(data, "syscall_active", bool, "execution_context")
_expect_key(data, "interrupts", list, "execution_context")
_expect_key(data, "irq_stack", dict, "execution_context")
_expect_key(data, "timestamp", str, "execution_context")


def validate_kernel_dna_response(payload: Any) -> None:
data = _expect_dict(payload, "kernel_dna")
_expect_key(data, "nucleotides", list, "kernel_dna")
_expect_key(data, "genes", list, "kernel_dna")
_expect_key(data, "mutations", list, "kernel_dna")
_expect_key(data, "timestamp", str, "kernel_dna")
95 changes: 20 additions & 75 deletions kernel_ai/views/pages.py
Original file line number Diff line number Diff line change
@@ -1,82 +1,27 @@
"""
Site pages: index, subsystem HTML, health, static files.

View implementations live in ``kernel_ai.webapp``; this module only wires URLs (lazy import avoids cycles).
"""
"""Site pages: index, subsystem HTML, and health."""
from flask import Blueprint
from kernel_ai.http import pages as h

bp = Blueprint("pages", __name__)


def _core():
from kernel_ai import webapp as core

return core


@bp.route("/")
def index():
return _core().index()


@bp.route("/linux-crypto-subsystem")
def linux_crypto_subsystem_page():
return _core().linux_crypto_subsystem_page()


@bp.route("/crypto")
def crypto_page_legacy():
return _core().crypto_page_legacy()


@bp.route("/linux-security-subsystem")
def linux_security_subsystem_page():
return _core().linux_security_subsystem_page()


@bp.route("/security")
def security_page_legacy():
return _core().security_page_legacy()


@bp.route("/linux-processes-subsystem")
def linux_processes_subsystem_page():
return _core().linux_processes_subsystem_page()


@bp.route("/processes")
def processes_page_legacy():
return _core().processes_page_legacy()


@bp.route("/linux-crypto-subsystem.html")
def linux_crypto_subsystem_html():
return _core().linux_crypto_subsystem_html()


@bp.route("/linux-security-subsystem.html")
def linux_security_subsystem_html():
return _core().linux_security_subsystem_html()


@bp.route("/linux-processes-subsystem.html")
def linux_processes_subsystem_html():
return _core().linux_processes_subsystem_html()


@bp.route("/linux-memory-subsystem")
def linux_memory_subsystem_page():
return _core().linux_memory_subsystem_page()


@bp.route("/linux-memory-subsystem.html")
def linux_memory_subsystem_html():
return _core().linux_memory_subsystem_html()


@bp.route("/health")
def health_check():
return _core().health_check()
_PAGE_ROUTES = [
("/", "index", h.index),
("/linux-crypto-subsystem", "linux_crypto_subsystem_page", h.linux_crypto_subsystem_page),
("/crypto", "crypto_page_legacy", h.crypto_page_legacy),
("/linux-security-subsystem", "linux_security_subsystem_page", h.linux_security_subsystem_page),
("/security", "security_page_legacy", h.security_page_legacy),
("/linux-processes-subsystem", "linux_processes_subsystem_page", h.linux_processes_subsystem_page),
("/processes", "processes_page_legacy", h.processes_page_legacy),
("/linux-crypto-subsystem.html", "linux_crypto_subsystem_html", h.linux_crypto_subsystem_html),
("/linux-security-subsystem.html", "linux_security_subsystem_html", h.linux_security_subsystem_html),
("/linux-processes-subsystem.html", "linux_processes_subsystem_html", h.linux_processes_subsystem_html),
("/linux-memory-subsystem", "linux_memory_subsystem_page", h.linux_memory_subsystem_page),
("/linux-memory-subsystem.html", "linux_memory_subsystem_html", h.linux_memory_subsystem_html),
("/health", "health_check", h.health_check),
]

for rule, endpoint, view_func in _PAGE_ROUTES:
bp.add_url_rule(rule, endpoint=endpoint, view_func=view_func)


# /static/<path:filename> is served by Flask's built-in static handler (see ``app.static_folder`` in webapp).
Loading