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

- 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:
StellaOps Bot
2025-11-23 00:35:33 +02:00
parent 2e89a92d92
commit 8d78dd219b
33 changed files with 1254 additions and 259 deletions

View File

@@ -0,0 +1,76 @@
# `/advisories/summary` API (draft v1)
Status: draft; aligns with LNM v1 (frozen 2025-11-17) and observation/linkset models already shipped in Concelier Core.
## Intent
- Provide graph overlays and consoles a deterministic summary of observations and linksets without derived verdicts.
- Preserve provenance and tenant isolation; results are stable for a given tenant + filter set.
## Request
- Method: `GET`
- Path: `/advisories/summary`
- Headers:
- `X-Stella-Tenant`: required.
- `X-Stella-Request-Id`: optional for tracing.
- Query parameters:
- `purl` (optional, repeatable) — filter by component coordinates.
- `alias` (optional, repeatable) — advisory aliases (CVE, GHSA, vendor IDs); case-insensitive; normalized and sorted server-side.
- `source` (optional, repeatable) — upstream source identifiers.
- `confidence_gte` (optional, decimal 01) — minimum linkset confidence.
- `conflicts_only` (optional, bool) — when `true`, return only summaries with conflicts present.
- `after` (optional, cursor) — opaque, tenant-scoped cursor for pagination.
- `take` (optional, int, default 100, max 500) — page size.
- `sort` (optional, enum: `advisory`, `observedAt`, default `advisory`) — always ascending and stable.
## Response (200)
```json
{
"meta": {
"tenant": "acme",
"count": 2,
"next": "opaque-cursor-or-null",
"sort": "advisory"
},
"items": [
{
"advisoryKey": "cve-2024-1234",
"aliases": ["GHSA-xxxx-yyyy", "CVE-2024-1234"],
"source": "nvd",
"observedAt": "2025-11-22T15:04:05Z",
"linksetId": "ls_01H9A8...",
"confidence": 0.82,
"conflicts": [
{ "field": "severity", "codes": ["severity-mismatch"], "sources": ["nvd", "vendor"] }
],
"counts": {
"observations": 3,
"conflictFields": 1
},
"provenance": {
"observationIds": ["obs_01H9...", "obs_01H9..."],
"schema": "lnm-1.0"
}
}
]
}
```
- Ordering: stable by `sort` then `advisoryKey` then `linksetId`.
- No derived verdicts or merged severity values; conflicts are emitted as structured markers only.
## Errors
- `400` `ERR_AOC_001`: missing/invalid tenant or unsupported filter.
- `400` `ERR_AOC_006`: `take` exceeds max or invalid cursor.
- `401/403`: auth/tenant scope failures.
- `429`: if per-tenant rate limits enforced (surface retry headers).
## Determinism & caching
- Response depends solely on tenant + normalized filters + underlying linksets; no clock-based variation beyond `observedAt` from stored records.
- Cache key (for optional summary cache):
- `tenant|purls(sorted)|aliases(sorted)|sources(sorted)|confidence_gte|conflicts_only|sort|take|after`
- Return transparency headers: `X-Stella-Cache-Key` (sha256-16), `X-Stella-Cache-Hit`, `X-Stella-Cache-Ttl`.
- Cache TTL should default to 0 (disabled) until validated; determinism required for hits.
## Notes
- Cursor must encode the final sort tuple (`advisoryKey`, `linksetId`, `observedAt`) to keep pagination stable when new data arrives.
- All string comparisons for filters are case-insensitive; server normalizes to lower-case and sorts before query execution.
- Conflicts mirror LNM conflict codes already produced by Core (no new codes introduced here).

View File

@@ -31,6 +31,21 @@ Status: draft · aligned with LNM v1 (frozen 2025-11-17)
- Timestamps use UTC ticks; content hashes retain upstream digest prefix (e.g., `sha256:`) to distinguish sources.
- Cache TTL defaults to 0 (disabled) unless configured; safe for offline/air-gapped deployments.
## Summary cache (for `/advisories/summary`)
- Optional, disabled by default; enables deterministic paging for graph/console overlays.
- Key material (pipe-delimited, normalized/sorted where applicable):
- `tenant`
- `purls[]` (sorted)
- `aliases[]` (sorted, lower-case)
- `sources[]` (sorted, lower-case)
- `confidence_gte`
- `conflicts_only`
- `sort`
- `take`
- `afterCursor` (opaque; includes last sort tuple)
- Transparency headers (if enabled): `X-Stella-Cache-Key` (sha256-16), `X-Stella-Cache-Hit`, `X-Stella-Cache-Ttl`.
- Ordering for cacheable results: `sort` (advisory|observedAt), then `advisoryKey`, then `linksetId`; cursor encodes the tuple to keep pagination stable when new linksets land.
## Testing notes
- Unit coverage: `AdvisoryChunkCacheKeyTests` (ordering, filter casing) and `AdvisoryChunkBuilderTests` (observationPath pointers influence chunk IDs).
- Integration tests should assert headers when cache is enabled; disable cache for tests that assert body-only determinism.
@@ -38,3 +53,4 @@ Status: draft · aligned with LNM v1 (frozen 2025-11-17)
## TODOs / follow-ups
- Add integration test that exercises a cache hit path and validates transparency headers.
- Document cache configuration knobs in `appsettings.*` once finalized.
- Add summary cache integration test once `/advisories/summary` endpoint is implemented.