feat(advisory-ai): Add deployment guide, Dockerfile, and Helm chart for on-prem packaging
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Introduced a comprehensive deployment guide for AdvisoryAI, detailing local builds, remote inference toggles, and scaling guidance. - Created a multi-role Dockerfile for building WebService and Worker images. - Added a docker-compose file for local and offline deployment. - Implemented a Helm chart for Kubernetes deployment with persistence and remote inference options. - Established a new API endpoint `/advisories/summary` for deterministic summaries of observations and linksets. - Introduced a JSON schema for risk profiles and a validator to ensure compliance with the schema. - Added unit tests for the risk profile validator to ensure functionality and error handling.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using Json.Schema;
|
||||
|
||||
namespace StellaOps.Policy.RiskProfile.Schema;
|
||||
|
||||
public static class RiskProfileSchemaProvider
|
||||
{
|
||||
private const string SchemaResource = "StellaOps.Policy.RiskProfile.Schemas.risk-profile-schema@1.json";
|
||||
|
||||
public static JsonSchema GetSchema()
|
||||
{
|
||||
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(SchemaResource)
|
||||
?? throw new InvalidOperationException($"Schema resource '{SchemaResource}' not found.");
|
||||
using var reader = new StreamReader(stream);
|
||||
var schemaText = reader.ReadToEnd();
|
||||
|
||||
return JsonSchema.FromText(schemaText);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stellaops.dev/schemas/risk-profile-schema@1.json",
|
||||
"title": "StellaOps RiskProfile v1",
|
||||
"type": "object",
|
||||
"required": [ "id", "version", "signals", "weights", "overrides" ],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Stable identifier for the risk profile (slug or URN)."
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[A-Za-z0-9.-]+)?$",
|
||||
"description": "SemVer for the profile definition."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Human-readable summary of the profile intent."
|
||||
},
|
||||
"signals": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [ "name", "source", "type" ],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Logical signal key (e.g., reachability, kev, exploit_chain)."
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Upstream provider or calculation origin."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [ "boolean", "numeric", "categorical" ]
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "JSON Pointer to the signal in the evidence document."
|
||||
},
|
||||
"transform": {
|
||||
"type": "string",
|
||||
"description": "Optional transform applied before weighting (e.g., log, normalize)."
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"description": "Optional unit for numeric signals."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"weights": {
|
||||
"type": "object",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"description": "Weight per signal name; weights are normalized by the consumer."
|
||||
},
|
||||
"overrides": {
|
||||
"type": "object",
|
||||
"required": [ "severity", "decisions" ],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"severity": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [ "when", "set" ],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"when": {
|
||||
"type": "object",
|
||||
"description": "Predicate over signals (key/value equals).",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": { "type": [ "string", "number", "boolean" ] }
|
||||
},
|
||||
"set": {
|
||||
"type": "string",
|
||||
"enum": [ "critical", "high", "medium", "low", "informational" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"decisions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [ "when", "action" ],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"when": {
|
||||
"type": "object",
|
||||
"description": "Predicate over signals (key/value equals).",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": { "type": [ "string", "number", "boolean" ] }
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": [ "allow", "review", "deny" ]
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Free-form metadata with stable keys.",
|
||||
"additionalProperties": { "type": [ "string", "number", "boolean", "array", "object", "null" ] }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JsonSchema.Net" Version="5.3.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="10.0.0-rc.2.25519.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Schemas\risk-profile-schema@1.json" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Text.Json;
|
||||
using Json.Schema;
|
||||
using StellaOps.Policy.RiskProfile.Schema;
|
||||
|
||||
namespace StellaOps.Policy.RiskProfile.Validation;
|
||||
|
||||
public sealed class RiskProfileValidator
|
||||
{
|
||||
private readonly JsonSchema _schema;
|
||||
|
||||
public RiskProfileValidator() : this(RiskProfileSchemaProvider.GetSchema())
|
||||
{
|
||||
}
|
||||
|
||||
public RiskProfileValidator(JsonSchema schema)
|
||||
{
|
||||
_schema = schema ?? throw new ArgumentNullException(nameof(schema));
|
||||
}
|
||||
|
||||
public ValidationResults Validate(string json)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
{
|
||||
throw new ArgumentException("Risk profile payload is required.", nameof(json));
|
||||
}
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
return _schema.Validate(document.RootElement);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user