first commit
This commit is contained in:
5
core/schemas/__init__.py
Normal file
5
core/schemas/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from .manifest import ModuleManifest
|
||||
from .results import AuditFindings, AuditResults
|
||||
from .status import AuditSeverity, AuditStatus
|
||||
|
||||
__all__ = ["AuditFindings", "AuditResults", "AuditSeverity", "AuditStatus", "ModuleManifest"]
|
||||
83
core/schemas/config.py
Normal file
83
core/schemas/config.py
Normal file
@@ -0,0 +1,83 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from core.schemas.status import AuditSeverity
|
||||
|
||||
|
||||
class LoggingOutput(StrEnum):
|
||||
STDOUT = "stdout"
|
||||
STDERR = "stderr"
|
||||
|
||||
|
||||
class LoggingConfig(BaseModel):
|
||||
level: str = Field("INFO", min_length=1)
|
||||
output: LoggingOutput = Field(LoggingOutput.STDOUT)
|
||||
|
||||
|
||||
class PluginPackagesConfig(BaseModel):
|
||||
renderers: list[str] = Field(default_factory=lambda: ["reporting.exporters"])
|
||||
transports: list[str] = Field(default_factory=lambda: ["reporting.transports"])
|
||||
modules: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class PluginConfigRef(BaseModel):
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
type: str = Field(min_length=1)
|
||||
|
||||
def payload(self) -> dict[str, Any]:
|
||||
return dict(self.model_extra or {})
|
||||
|
||||
|
||||
class ReportOutputConfig(BaseModel):
|
||||
renderer: PluginConfigRef = Field()
|
||||
transport: PluginConfigRef = Field()
|
||||
|
||||
|
||||
class ReportsConfig(BaseModel):
|
||||
outputs: list[ReportOutputConfig] = Field(min_length=1)
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
exclude_categories: list[str] = Field(default_factory=list)
|
||||
|
||||
allow_failures_below: AuditSeverity = Field()
|
||||
strict_mode: bool = Field()
|
||||
fail_fast: bool = Field(False)
|
||||
dry_run: bool = Field(False)
|
||||
max_concurrency: int = Field(4, ge=1)
|
||||
logging: LoggingConfig = Field(default_factory=LoggingConfig)
|
||||
|
||||
plugin_packages: PluginPackagesConfig = Field(default_factory=PluginPackagesConfig)
|
||||
reports: ReportsConfig = Field()
|
||||
|
||||
modules: dict[str, dict[str, Any]] = Field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedPluginConfig:
|
||||
type: str
|
||||
config: BaseModel
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedReportOutput:
|
||||
renderer: ResolvedPluginConfig
|
||||
transport: ResolvedPluginConfig
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedConfig:
|
||||
exclude_categories: list[str]
|
||||
allow_failures_below: AuditSeverity
|
||||
strict_mode: bool
|
||||
fail_fast: bool
|
||||
dry_run: bool
|
||||
max_concurrency: int
|
||||
logging: LoggingConfig
|
||||
plugin_packages: PluginPackagesConfig
|
||||
reports: list[ResolvedReportOutput]
|
||||
modules: dict[str, BaseModel]
|
||||
15
core/schemas/manifest.py
Normal file
15
core/schemas/manifest.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class ModuleManifest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
extra="forbid",
|
||||
frozen=True,
|
||||
)
|
||||
|
||||
identifier: str = Field(pattern=r"^[a-z][a-z0-9_-]*$")
|
||||
name: str = Field(min_length=1)
|
||||
category: str = Field(min_length=1)
|
||||
version: str = Field(pattern=r"^\d+\.\d+\.\d+$")
|
||||
api_version: str = Field("1", pattern=r"^\d+$")
|
||||
description: str = ""
|
||||
32
core/schemas/modules.py
Normal file
32
core/schemas/modules.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from core.base import BaseWorker
|
||||
from core.schemas import ModuleManifest
|
||||
from reporting.models import PluginRuntimeError
|
||||
|
||||
WorkerBuilder = Callable[[BaseModel | dict[str, Any]], BaseWorker]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LoadedModule:
|
||||
package_name: str
|
||||
manifest: ModuleManifest
|
||||
build_worker: WorkerBuilder
|
||||
config_model: type[BaseModel]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LoadedWorker:
|
||||
worker: BaseWorker
|
||||
manifest: ModuleManifest
|
||||
config: BaseModel | dict[str, Any]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ModuleLoadResult:
|
||||
loaded_workers: list[LoadedWorker]
|
||||
errors: list[PluginRuntimeError]
|
||||
17
core/schemas/results.py
Normal file
17
core/schemas/results.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from core.schemas.status import AuditSeverity, AuditStatus
|
||||
|
||||
|
||||
class AuditFindings(BaseModel):
|
||||
name: str = Field()
|
||||
description: str = Field("")
|
||||
severity: AuditSeverity = Field()
|
||||
|
||||
|
||||
class AuditResults(BaseModel):
|
||||
status: AuditStatus = Field()
|
||||
findings: list[AuditFindings] = Field()
|
||||
risk_level: float = Field(
|
||||
description="value from 0.0 to 1.0, indicating how dangerous the auditresults are."
|
||||
)
|
||||
14
core/schemas/status.py
Normal file
14
core/schemas/status.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
class AuditStatus(StrEnum):
|
||||
PASS = "pass"
|
||||
SKIPPED = "skipped"
|
||||
FAIL = "fail"
|
||||
|
||||
|
||||
class AuditSeverity(StrEnum):
|
||||
CRITICAL = "critical"
|
||||
HIGH = "high"
|
||||
MEDIUM = "medium"
|
||||
LOW = "low"
|
||||
Reference in New Issue
Block a user