VEX Auto-Generation Flow

Implementation status (reconciled against src/ 2026-05-30). This document describes an aspirational end-to-end “VEX auto-generation” pipeline. Most of the flow as originally written — an autonomous AdvisoryAI that gathers evidence, decides the VEX status, emits a full OpenVEX statement, routes it through a Console review/approve UI, then signs and stores it in VexLens with a Rekor transparency-log entry — is NOT IMPLEMENTED as a single pipeline. Three real, narrower capabilities exist in code today and are documented inline below:

  1. AdvisoryAI /v1/advisory-ai/justifydrafts justification text (not a full VEX document) for a user-proposed status + justification type, returning a confidence score and evidence suggestions. The human chooses the status; the AI does not decide it. Source: src/AdvisoryAI/StellaOps.AdvisoryAI.WebService/Program.cs (HandleJustify) and Contracts/JustifyContracts.cs.
  2. VexLens computes deterministic, trust-weighted consensus over VEX statements that were already ingested (via VexHub). It does not generate, author, sign, or store newly-authored VEX statements, and it has no AdvisoryAI integration. Source: src/VexLens/StellaOps.VexLens/** and src/VexLens/StellaOps.VexLens.WebService/Extensions/VexLensEndpointExtensions.cs.
  3. Console source includes a dedicated AI-justify panel (AiJustifyPanelComponent, task VEX-AI-009) and a VEX create-workflow wizard (VexCreateWorkflowComponent, task VEX-AI-011). The justify panel calls AdvisoryAI /justify, renders the draft, confidence, and a review checklist, and emits a chosen justification; the create-workflow walks vulnerability → status → justification → evidence → review and then POSTs to a VexHub create endpoint. Caveat: that create endpoint (POST /api/v1/vex/statements / …/statements/simple, expected by src/Web/StellaOps.Web/src/app/core/api/vex-hub.client.ts) does not exist server-side — VexHub’s WebService only exposes read endpoints plus one admin POST /api/v1/vex/conflicts/resolve. The Console therefore does not expose a Create action: …/vex/create redirects to VEX search until a real, authenticated create endpoint exists. The wizard source remains dormant.

Sections that describe non-existent surfaces (the auto-approve YAML, the VexDraftRequest/VexDraftResponse schemas, the vex_drafts_* metrics, the vex.draft.* log events, signing + Rekor) are flagged NOT IMPLEMENTED where they appear and retained as roadmap intent. The earlier blanket claim that “the Console draft-review UI” does not exist was incorrect and is corrected below (the UI exists; its backend does not).

Overview

The VEX (Vulnerability Exploitability eXchange) Auto-Generation Flow describes how StellaOps assists in creating VEX statements by analyzing reachability data, runtime observations, and historical patterns. This flow combines automated analysis with human review to produce accurate exploitability assessments.

Audience: security analysts reviewing VEX data and engineers integrating with AdvisoryAI and VexLens. Read the implementation-status banner above first — most of the end-to-end pipeline is aspirational; the live surfaces are AdvisoryAI /justify, VexLens consensus, and Console VEX search/read workflows.

Business Value: Reduce false positive burden by automatically identifying vulnerabilities that are not exploitable in the specific deployment context.

Actors

ActorTypeRoleStatus
Security AnalystHumanReviews VEX statements and consensus; may propose status/justification through future authoringRead workflows implemented; Console authoring is unavailable until the backend create contract exists (see Step 6)
AdvisoryAIServiceAI-assisted justification text drafting via /v1/advisory-ai/justify; does not decide statusImplemented (justification drafting only)
ReachGraphServiceProvides reachability analysis (supplied to AdvisoryAI as a reachabilityScore context field, not auto-queried by a VEX pipeline)Partial — no auto-wired VEX pipeline
SignalsServiceProvides runtime observations (not consumed by any VEX-generation pipeline)NOT IMPLEMENTED for this flow
VexLensServiceComputes trust-weighted consensus over already-ingested VEX statements; does not author/sign/distribute new VEXImplemented (consensus only)
VexHubServiceIngests/normalizes/stores VEX statements and is the intended authoring backend the Console create-workflow targets. No author/create endpoint exists yet — VexHub’s WebService only exposes read endpoints plus one admin POST /api/v1/vex/conflicts/resolvePartial — read + conflict-resolve only; create endpoint NOT IMPLEMENTED
Console (Web UI)FrontendHosts VEX search/read workflows; retains dormant AI-justify and create-workflow sourceRead UI implemented; Create is hidden and …/vex/create redirects to search because the VexHub create endpoint does not exist
ScannerServiceProvides SBOM context (supplied to AdvisoryAI as a free-text sbomContext/callGraphSummary field, not auto-queried)Partial — manual context only

Prerequisites

VEX Statuses

Source of truth: the VexStatus enum in src/VexLens/StellaOps.VexLens/Models/NormalizedVexModels.cs (and the mirrored enum in Integration/VexSignalEmitter.cs). VexLens carries a fifth status, unknown, with dedicated rationale/provenance-trace handling — it is not optional.

StatusDescription
not_affectedVulnerability not exploitable
affectedVulnerability is exploitable
fixedVulnerability has been remediated
under_investigationStatus being determined
unknownUnresolved / no usable consensus — surfaces an unknownRationale and unknownProvenanceTrace

The “Automation Confidence” column from earlier revisions was removed: there is no automated status-decisioning engine in code, so per-status automation confidence has no implementation backing.

Justification Types (OpenVEX)

Matches the VexJustification enum in src/VexLens/StellaOps.VexLens/Models/NormalizedVexModels.cs exactly.

JustificationDescription
component_not_presentVulnerable component not in product
vulnerable_code_not_presentSpecific vulnerable code not included
vulnerable_code_not_in_execute_pathCode present but unreachable
vulnerable_code_cannot_be_controlled_by_adversaryAttack vector blocked
inline_mitigations_already_existCompensating controls in place

Authorization

Reconciled against src/Authority/.../StellaOpsScopes.cs and the two service Program.cs files.

SurfaceAuth requirement (as enforced in code)Notes
VexLens read endpoints (POST /api/v1/vexlens/consensus*, GET /api/v1/vexlens/projections*, /stats, /conflicts, /deltas/compute, /gating/*)ASP.NET policy vexlens.readRegistered by VexLens.WebService/Program.cs and canonically declared as StellaOpsScopes.VexLensRead; the shipped Standard Authority profile grants it to the Console and CLI clients, and migration 010 repairs an existing/drifted Console client grant.
VexLens issuer-directory endpoints (/api/v1/vexlens/issuers*)ASP.NET policy vexlens.writeRegistered by VexLens.WebService/Program.cs, canonically declared as StellaOpsScopes.VexLensWrite, and granted to the first-party Console and CLI clients by the shipped Standard Authority profile.
AdvisoryAI POST /v1/advisory-ai/justifyAny of advisory:run, advisory:justify, advisory-ai:operate, advisory-ai:admin (handler checks the token’s scope set)Only advisory-ai:operate and advisory-ai:admin are in the canonical catalog; advisory:run and advisory:justify are accepted by the handler but not defined in StellaOpsScopes.cs.

Flagged divergence: advisory:run and advisory:justify are enforced in AdvisoryAI service code but remain absent from the canonical scope catalog. The vexlens.* gap is closed: both strings are canonical Authority scopes and are present in the shipped Standard client grants.

Flow Diagram

NOT IMPLEMENTED as drawn. The sequence below is the target design. In code today there is no service that auto-queries Scanner, ReachGraph, and Signals on the analyst’s behalf, no autonomous status decision, and no VexLens “store + sign” step. What actually exists:

  • The analyst (or a calling tool — in the Console, the AiJustifyPanelComponent) gathers context manually and calls AdvisoryAI /v1/advisory-ai/justifywith the already-chosen status and justification type, plus optional free-text context (sbomContext, callGraphSummary, reachabilityScore, relatedVexStatements). AdvisoryAI returns drafted justification text, a suggestedJustificationType, a confidence score, and evidence suggestions.
  • The Console retains VEX create-workflow source for vulnerability → status → justification → evidence → review, but does not expose it. …/vex/create redirects to search because the VexHub create endpoint does not exist server-side yet (see Step 6).
  • Separately, VexLens computes consensus over VEX statements already ingested from VexHub (POST /api/v1/vexlens/consensus), with no authoring step.

The ASCII sequence is retained as roadmap intent.

┌─────────────────────────────────────────────────────────────────────────────────┐
│              VEX Auto-Generation Flow (TARGET DESIGN — not implemented)           │
└─────────────────────────────────────────────────────────────────────────────────┘

┌─────────┐  ┌───────────┐  ┌───────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
│ Analyst │  │AdvisoryAI │  │ ReachGraph│  │ Signals │  │ VexLens │  │ Scanner │
└────┬────┘  └─────┬─────┘  └─────┬─────┘  └────┬────┘  └────┬────┘  └────┬────┘
     │             │              │             │            │            │
     │ Review      │              │             │            │            │
     │ finding     │              │             │            │            │
     │────────────>│              │             │            │            │
     │             │              │             │            │            │
     │             │ Get SBOM     │             │            │            │
     │             │ context      │             │            │            │
     │             │────────────────────────────────────────────────────>│
     │             │              │             │            │            │
     │             │ SBOM +       │             │            │            │
     │             │ call graph   │             │            │            │
     │             │<────────────────────────────────────────────────────│
     │             │              │             │            │            │
     │             │ Query reach  │             │            │            │
     │             │─────────────>│             │            │            │
     │             │              │             │            │            │
     │             │              │ Analyze     │            │            │
     │             │              │ call paths  │            │            │
     │             │              │───┐         │            │            │
     │             │              │   │         │            │            │
     │             │              │<──┘         │            │            │
     │             │              │             │            │            │
     │             │ K4 state +   │             │            │            │
     │             │ evidence     │             │            │            │
     │             │<─────────────│             │            │            │
     │             │              │             │            │            │
     │             │ Query runtime│             │            │            │
     │             │─────────────────────────────>            │            │
     │             │              │             │            │            │
     │             │              │             │ Check      │            │
     │             │              │             │ invocations│            │
     │             │              │             │───┐        │            │
     │             │              │             │   │        │            │
     │             │              │             │<──┘        │            │
     │             │              │             │            │            │
     │             │ Runtime      │             │            │            │
     │             │ evidence     │             │            │            │
     │             │<─────────────────────────────            │            │
     │             │              │             │            │            │
     │             │ Analyze      │             │            │            │
     │             │ with LLM     │             │            │            │
     │             │───┐          │             │            │            │
     │             │   │          │             │            │            │
     │             │<──┘          │             │            │            │
     │             │              │             │            │            │
     │ VEX draft   │              │             │            │            │
     │ + confidence│              │             │            │            │
     │<────────────│              │             │            │            │
     │             │              │             │            │            │
     │ [Review]    │              │             │            │            │
     │ Approve/    │              │             │            │            │
     │ Modify      │              │             │            │            │
     │───┐         │              │             │            │            │
     │   │         │              │             │            │            │
     │<──┘         │              │             │            │            │
     │             │              │             │            │            │
     │ Submit VEX  │              │             │            │            │
     │────────────────────────────────────────────────────────>            │
     │             │              │             │            │            │
     │             │              │             │            │ Store      │
     │             │              │             │            │ + sign     │
     │             │              │             │            │───┐        │
     │             │              │             │            │   │        │
     │             │              │             │            │<──┘        │
     │             │              │             │            │            │
     │ VEX ID      │              │             │            │            │
     │<────────────────────────────────────────────────────────            │
     │             │              │             │            │            │

Step-by-Step

1. Finding Review Initiation

Analyst selects finding for VEX assessment:

{
  "scan_id": "scan-abc123",
  "cve": "CVE-2024-1234",
  "package": "pkg:npm/lodash@4.17.20",
  "severity": "critical",
  "current_status": "affected",
  "request": "assess_exploitability"
}

Reconciliation: there is no assess_exploitability request type and no endpoint that takes a scan_id + cve and returns a status recommendation. The implemented entry point is AdvisoryAI POST /v1/advisory-ai/justify (see Step 3), which requires the caller to already supply the ProposedStatus.

2. Context Gathering

NOT IMPLEMENTED as auto-gathering. AdvisoryAI does not call Scanner, ReachGraph, or Signals to assemble this context. The /justify request accepts a small, caller-supplied contextData object instead (reachabilityScore, codeSearchResults, sbomContext (free text), callGraphSummary (free text), relatedVexStatements (list of strings)). The rich SBOM/reachability/runtime JSON shapes below are illustrative of what a caller might summarize into those fields — they are not the wire format and are not produced by any service automatically.

SBOM Context

{
  "component": {
    "purl": "pkg:npm/lodash@4.17.20",
    "locations": ["/app/node_modules/lodash"],
    "dependents": ["express", "webpack"],
    "scope": "runtime"
  },
  "call_graph": {
    "entry_points": ["src/api/handler.js", "src/worker/processor.js"],
    "functions_imported": ["_.get", "_.merge", "_.template"]
  }
}

Reachability Analysis

{
  "package": "pkg:npm/lodash@4.17.20",
  "k4_state": "StaticallyReachable",
  "vulnerable_function": "_.template",
  "analysis": {
    "function_imported": true,
    "call_sites": 3,
    "call_paths": [
      {
        "path": ["src/api/handler.js:45", "lib/renderer.js:12", "_.template"],
        "reachable": true
      }
    ]
  }
}

Runtime Signals

{
  "package": "pkg:npm/lodash@4.17.20",
  "observation_period": "30d",
  "signals": {
    "function_invocations": {
      "_.get": 15234,
      "_.merge": 892,
      "_.template": 0
    },
    "vulnerable_function_called": false,
    "last_check": "2024-12-29T10:00:00Z"
  }
}

3. AI-Assisted Analysis

The implemented surface is POST /v1/advisory-ai/justify(handler HandleJustify in AdvisoryAI.WebService/Program.cs; contracts in Contracts/JustifyContracts.cs). The caller supplies the proposed status and justification type; AdvisoryAI drafts the justification text and a confidence score. It does not decide the status, and it does not return an analysis/recommendation object with a status field as shown in earlier revisions.

Actual request (AiJustifyApiRequest):

{
  "cveId": "CVE-2024-1234",
  "productRef": "pkg:npm/lodash@4.17.20",
  "proposedStatus": "not_affected",
  "justificationType": "vulnerable_code_not_in_execute_path",
  "contextData": {
    "reachabilityScore": 0.2,
    "codeSearchResults": 3,
    "sbomContext": "lodash@4.17.20 present in /app/node_modules",
    "callGraphSummary": "_.template imported; 3 call sites appear unused",
    "relatedVexStatements": ["upstream not_affected (vendor)"]
  },
  "correlationId": "corr-abc123"
}

Actual response (AiJustifyApiResponse):

{
  "justificationId": "just-789",
  "draftJustification": "The vulnerable _.template function is imported but no reachable call path exercises it with adversary-controlled input.",
  "suggestedJustificationType": "vulnerable_code_not_in_execute_path",
  "confidenceScore": 0.85,
  "evidenceSuggestions": [
    "Attach the call-graph excerpt showing the unused import",
    "Attach runtime telemetry covering the observation window"
  ],
  "modelVersion": "<inference-profile-version>",
  "generatedAt": "2024-12-29T10:30:00Z",
  "traceId": "trace-..."
}

4. VEX Draft Generation

NOT IMPLEMENTED. No service emits a full OpenVEX document (@context/@id/statements[...]) as an automated “draft VEX”. The /justify endpoint returns only the justification text and metadata shown in Step 3. Authoring a complete OpenVEX statement, assigning a draft @id, and the requires_human_review flag are roadmap intent. The OpenVEX shape below is retained as the target document format a future authoring step would produce, and matches the OpenVEX v0.2.0 schema StellaOps consumes elsewhere.

{
  "draft_vex": {
    "@context": "https://openvex.dev/ns/v0.2.0",
    "@id": "https://stellaops.local/vex/draft/vex-draft-123",
    "author": "StellaOps AdvisoryAI",
    "timestamp": "2024-12-29T10:30:00Z",
    "version": 1,
    "statements": [
      {
        "vulnerability": {
          "@id": "https://nvd.nist.gov/vuln/detail/CVE-2024-1234"
        },
        "products": [
          {
            "@id": "pkg:oci/myorg/app@sha256:abc123",
            "subcomponents": [
              {"@id": "pkg:npm/lodash@4.17.20"}
            ]
          }
        ],
        "status": "not_affected",
        "justification": "vulnerable_code_not_in_execute_path",
        "impact_statement": "The vulnerable _.template function is imported but never invoked. Runtime monitoring over 30 days confirms zero executions."
      }
    ]
  },
  "confidence": 0.85,
  "evidence_refs": [
    "reachability:reach-analysis-456",
    "signals:runtime-obs-789"
  ],
  "requires_human_review": true
}

5. Human Review

PARTIALLY IMPLEMENTED (corrected). A dedicated review surface does exist in the Console (src/Web/), contrary to earlier revisions of this doc:

  • AiJustifyPanelComponent(src/Web/StellaOps.Web/src/app/features/vex-hub/ai-justify-panel.component.ts, task VEX-AI-009) renders a config form (proposed status, justification type, product ref, optional context), calls AdvisoryAI /justify, then shows the drafted text in an editable box, a circular confidence gauge, the suggested justification type, evidence suggestions, and a three-item review checklist (“verified accurate”, “evidence attached”, “reviewed by a team member”). The “Use This Justification” button is disabled until the checklist is complete and emits the chosen justification text + type.
  • VexCreateWorkflowComponent(…/features/vex-hub/vex-create-workflow.component.ts, task VEX-AI-011) implements a 5-step wizard in source (vulnerability → status → justification → evidence → review). It is not reachable from the Console; …/vex/create redirects to search while the required backend create endpoint is absent.

What is not implemented is the autonomous “AI Recommendation: status + justification + confidence” decision shown in the mockup — the AI drafts text for a status the human already chose; it does not recommend the status. The final submit also has no live backend (see Step 6). The ASCII mockup below remains illustrative of the broad layout; the real panels are the components named above.

┌─────────────────────────────────────────────────────────────────┐
│ VEX Draft Review                                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│ CVE: CVE-2024-1234 (Critical)                                   │
│ Package: lodash@4.17.20                                         │
│ Image: docker.io/myorg/app:v1.2.3                              │
│                                                                  │
│ ┌─ AI Recommendation ──────────────────────────────────────────┐│
│ │ Status: not_affected                                         ││
│ │ Justification: vulnerable_code_not_in_execute_path           ││
│ │ Confidence: 85%                                              ││
│ └──────────────────────────────────────────────────────────────┘│
│                                                                  │
│ ┌─ Evidence ───────────────────────────────────────────────────┐│
│ │ ✓ Static analysis: 3 potential call sites found              ││
│ │ ✓ Runtime (30d): 0 invocations of _.template                 ││
│ │ ✓ Call graph: paths exist but appear unused                  ││
│ │ ⚠ Note: Function is imported in production code              ││
│ └──────────────────────────────────────────────────────────────┘│
│                                                                  │
│ [Approve] [Modify] [Reject] [Request More Analysis]             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

6. VEX Submission

NOT IMPLEMENTED end-to-end. Two distinct facts:

  • VexLens is not the authoring backend. It does not sign or “publish” authored VEX statements and emits no Rekor transparency-log entry for them. VexLens verifies signatures and consumes transparency-log proofs on incoming ingested statements (see StellaOps.VexLens.Core/Signature/ISignatureVerifier/SignatureVerifier, the TransparencyLogEntry model, and the verification metrics vexlens.signature.*), and it stores consensus projections (IConsensusProjectionStore) — not signed authored VEX.
  • VexHub is the intended authoring backend, but its create endpoint is missing. The Console create-workflow POSTs to POST /api/v1/vex/statements and …/statements/simple (per vex-hub.client.ts), but the VexHub WebService (src/VexHub/StellaOps.VexHub.WebService/Extensions/VexHubEndpointExtensions.cs) exposes only read endpoints (/cve/{id}, /package/{purl}, /search, /stats, /export, …) plus one admin write — POST /api/v1/vex/conflicts/resolve. There is no server-side handler for creating an authored statement, so the submission round-trip currently has no live backend. To avoid a dead-end workflow, the Console hides the Create action and redirects direct visits to …/vex/create back to VEX search.

Signing + transparency anchoring for newly-authored VEX, and the VexHub create endpoint itself, are roadmap intent. The shape below is illustrative only and does not match any implemented response.

{
  "vex_id": "vex-789ghi",
  "status": "published",
  "signed_by": "analyst@acme.com",
  "signature": {
    "keyid": "sha256:analyst-key-fingerprint",
    "sig": "base64:signature..."
  },
  "transparency_log": {
    "rekor_log_index": 12345678,
    "log_id": "sha256:rekor-log..."
  }
}

Automation Levels

NOT IMPLEMENTED. There is no vex_automation configuration block, auto-approve engine, or review_timeout mechanism in code. Confidence thresholds are not used to auto-approve anything. AdvisoryAI returns a confidenceScore on /justify, but nothing acts on it automatically. The YAML below is target design, retained for roadmap intent.

Fully Automated (High Confidence)

vex_automation:
  auto_approve:
    - condition: component_not_present
      confidence_threshold: 0.99
    - condition: fixed_version_deployed
      confidence_threshold: 0.95

Semi-Automated (Human Review)

vex_automation:
  require_review:
    - condition: runtime_not_observed
      confidence_threshold: 0.70
      review_timeout: 24h

Manual Only

vex_automation:
  manual_only:
    - condition: affected
    - condition: inline_mitigations

Data Contracts

Reconciliation. The VexDraftRequest / VexDraftResponse schemas in earlier revisions do not exist in code (no scan_id/recommended_status request, no draft_id/recommended_status/expires_at response). The two contract families that do exist are: the AdvisoryAI justify contract and the VexLens consensus contract. Both are documented below with their source files.

AdvisoryAI Justify Contract (implemented)

Source: src/AdvisoryAI/StellaOps.AdvisoryAI.WebService/Contracts/JustifyContracts.cs.

// POST /v1/advisory-ai/justify  (AiJustifyApiRequest)
interface AiJustifyApiRequest {
  cveId: string;                 // required
  productRef: string;            // required (PURL, artifact digest, etc.)
  proposedStatus: string;        // required — caller chooses the status
  justificationType: string;     // required — OpenVEX justification label
  contextData?: {
    reachabilityScore?: number;        // 0..1
    codeSearchResults?: number;
    sbomContext?: string;              // free-text summary
    callGraphSummary?: string;         // free-text summary
    relatedVexStatements?: string[];
  };
  correlationId?: string;
}

// 200 OK  (AiJustifyApiResponse)
interface AiJustifyApiResponse {
  justificationId: string;
  draftJustification: string;          // the AI-drafted justification TEXT
  suggestedJustificationType: string;
  confidenceScore: number;             // 0..1
  evidenceSuggestions: string[];
  modelVersion: string;
  generatedAt: string;                 // ISO-8601
  traceId?: string;
}

VexLens Consensus Contract (implemented)

Source: src/VexLens/StellaOps.VexLens/Api/ConsensusApiModels.cs and StellaOps.VexLens.WebService/Extensions/VexLensEndpointExtensions.cs.

// POST /api/v1/vexlens/consensus  (ComputeConsensusRequest)
interface ComputeConsensusRequest {
  vulnerabilityId: string;
  productKey: string;            // PURL or CPE
  tenantId?: string;             // also accepted via X-StellaOps-TenantId header
  mode?: 'HighestWeight' | 'WeightedVote' | 'Lattice' | 'AuthoritativeFirst';
  minimumWeightThreshold?: number;
  storeResult?: boolean;
  emitEvent?: boolean;
}

// 200 OK  (ComputeConsensusResponse)
interface ComputeConsensusResponse {
  vulnerabilityId: string;
  productKey: string;
  status: VexStatus;             // not_affected | affected | fixed | under_investigation | unknown
  justification?: VexJustification;
  confidenceScore: number;
  outcome: 'Unanimous' | 'Majority' | 'Plurality' | 'ConflictResolved' | 'NoData' | 'Indeterminate';
  rationale: { summary: string; factors: string[]; statusWeights: Record<string, number>; };
  contributions: Array<{ statementId: string; issuerId?: string; status: VexStatus; justification?: VexJustification; weight: number; contribution: number; isWinner: boolean; }>;
  conflicts?: Array<{ statement1Id: string; statement2Id: string; status1: VexStatus; status2: VexStatus; severity: string /* 'Low'|'Medium'|'High'|'Critical' */; resolution: string; }>;
  projectionId?: string;
  computedAt: string;
}

A consensus:withProof variant adds a proof object (per-issuer verdicts, trust weights, digest, raw proof JSON), and a consensus:batch variant evaluates multiple pairs. See the source for the full ProofResponse shape.

Confidence Scoring

NOT IMPLEMENTED as a fixed table. No code uses this evidence-type → base-confidence + modifier lookup. The two real confidence figures are: (1) AdvisoryAI’s confidenceScore returned by /justify, produced by the inference profile; and (2) VexLens’s confidenceScore, computed from trust-weighted consensus (vexlens.consensus.confidence histogram), not from evidence type. The table below is retained as roadmap intent for a future evidence-weighting model.

Evidence TypeBase ConfidenceModifiers
Component not in SBOM0.99-
Fixed version confirmed0.95-
Runtime never invoked (30d+)0.85+0.05 per additional 30d
Static unreachable0.70+0.10 with runtime confirm
AI code analysis0.60Requires human review
Historical pattern match0.50Requires human review

Error Handling

Aspirational. The “fall back to static analysis / template-based / queue for retry” behaviors are not wired (there is no auto-gathering pipeline to degrade and no signing step to retry). What is implemented today: /justify returns 400 Bad Request on invalid input (InvalidOperationException) and 403 Forbidden when the caller lacks an accepted scope; VexLens consensus returns 400 on missing/unparseable inputs and evaluates each batch pair independently (a failing pair is counted in failureCount without aborting the batch).

ErrorRecovery (target design)
Reachability unavailableLower confidence, require review
Runtime signals missingUse static analysis only
AI analysis timeoutFall back to template-based
Signing failureQueue for retry

Observability

Metrics

Reconciled. The vex_drafts_* / vex_confidence_score / vex_review_duration_seconds metrics do not exist. The implemented VexLens meter (StellaOps.VexLens, see Observability/VexLensMetrics.cs) emits the metrics below (selected). AdvisoryAI /justify is traced via the advisory_ai.justify activity rather than a dedicated metric.

MetricTypeLabels
vexlens.consensus.computed_totalCounterstatus, outcome
vexlens.consensus.conflicts_totalCounterstatus, outcome
vexlens.consensus.confidenceHistogramstatus, outcome
vexlens.consensus.status_changes_totalCounterstatus, outcome
vexlens.trust.weights_computed_total / vexlens.trust.weight_valueCounter / Histogramissuer_category
vexlens.projection.stored_total / vexlens.projection.queries_totalCounterstatus, status_changed / result_count_bucket
vexlens.signature.verified_total / vexlens.signature.failures_totalCounterformat, valid
vexlens.issuer.registered_total / vexlens.issuer.revoked_totalCountercategory, trust_tier

Key Log Events

Reconciled. There are no vex.draft.* / vex.published structured log event names. VexLens uses numeric event IDs in VexLensLogEvents (Observability/VexLensMetrics.cs); AdvisoryAI justify is observable via the advisory_ai.justify activity span (tags: advisory.cve_id, advisory.product_ref, advisory.proposed_status, advisory.justification_id, advisory.confidence).

Event (VexLensLogEvents)IDNotes
ConsensusCompleted5002Consensus computed for a vuln/product pair
ConflictDetected5004Issuer dispositions disagree
StatusChanged5005Consensus status changed vs. prior projection
NoStatementsAvailable5006No ingested statements for the pair
ProjectionStored6001Consensus projection persisted
IssuerRegistered / IssuerRevoked7001 / 7002Issuer-directory mutations