mirror of
https://github.com/mvt-project/mvt.git
synced 2026-09-03 08:30:51 +02:00
feat: add versioned output schemas
This commit is contained in:
@@ -82,6 +82,10 @@ class ExampleCustomModule(MVTModule):
|
||||
return None
|
||||
```
|
||||
|
||||
Custom modules should declare an `output_model` using a Pydantic `RootModel`.
|
||||
This validates saved results and lets consumers obtain the module's JSON Schema.
|
||||
See [Output schemas](output-schemas.md#custom-modules) for a complete example.
|
||||
|
||||
Use `supported_commands` to declare the platform/command pairs a module
|
||||
supports. Empty `supported_commands` means the module will not run and MVT logs
|
||||
a warning. This explicit declaration is required for every command. Supported
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Output schemas
|
||||
|
||||
MVT validates its JSON output with versioned Pydantic models. The schema version
|
||||
used for a run is recorded as `output_schema_version` in `info.json`.
|
||||
|
||||
MVT preserves the established on-disk format: most module files contain an array
|
||||
of result objects, while modules whose results are naturally grouped contain an
|
||||
object keyed by source or namespace. Detection files and `alerts.json` contain
|
||||
arrays of alert objects. Timestamps remain strings because their timezone and
|
||||
precision depend on the source artifact.
|
||||
|
||||
## Exporting JSON Schema
|
||||
|
||||
Both platform commands can print a versioned JSON Schema bundle:
|
||||
|
||||
```bash
|
||||
mvt-ios schemas
|
||||
mvt-android schemas
|
||||
```
|
||||
|
||||
Use `--output` to write one Draft 2020-12 JSON Schema file for each output:
|
||||
|
||||
```bash
|
||||
mvt-ios schemas --output ./mvt-ios-schemas
|
||||
mvt-android schemas --output ./mvt-android-schemas
|
||||
```
|
||||
|
||||
## Python API
|
||||
|
||||
Models and schema discovery functions are available from `mvt.schemas`:
|
||||
|
||||
```python
|
||||
from mvt.schemas import get_output_model
|
||||
|
||||
SafariHistoryOutput = get_output_model("safari_history", platform="ios")
|
||||
validated = SafariHistoryOutput.model_validate(records)
|
||||
json_schema = SafariHistoryOutput.model_json_schema()
|
||||
```
|
||||
|
||||
Common outputs have dedicated field-level models. Built-in module outputs have a
|
||||
declared root shape, and modules with an established dedicated record model expose
|
||||
its complete field schema.
|
||||
|
||||
## Custom modules
|
||||
|
||||
Custom modules can publish a precise contract by assigning a Pydantic root model
|
||||
to `output_model`:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, RootModel
|
||||
|
||||
from mvt.common.module import MVTModule
|
||||
|
||||
|
||||
class ExampleRecord(BaseModel):
|
||||
message: str
|
||||
timestamp: str | None = None
|
||||
|
||||
|
||||
class ExampleOutput(RootModel[list[ExampleRecord]]):
|
||||
pass
|
||||
|
||||
|
||||
class ExampleModule(MVTModule):
|
||||
output_model = ExampleOutput
|
||||
```
|
||||
|
||||
For compatibility, a custom module without `output_model` can still write an
|
||||
array or object containing JSON values. MVT logs a warning when it uses this
|
||||
generic contract. A future major release may require custom modules to declare
|
||||
their output models.
|
||||
|
||||
## Compatibility policy
|
||||
|
||||
Within one output schema major version, required fields are not removed and field
|
||||
types are not narrowed. New optional fields may be added. A breaking output
|
||||
change requires a new schema major version and a migration note.
|
||||
Reference in New Issue
Block a user