Files
git.stella-ops.org/docs/modules/concelier/api/observations.md

8.6 KiB

Observations API (v1)

Status: stable; aligns with LNM v1 (frozen 2025-11-17).

Intent

  • Provide raw observation retrieval for graph overlays, audit trails, and detailed provenance inspection.
  • Observations are the immutable evidence units that feed into linkset aggregation.
  • Each observation represents a single upstream source's statement about an advisory at a point in time.

Endpoints

Query Observations

  • Method: GET
  • Path: /advisories/observations

Get Observations for Advisory

  • Method: GET
  • Path: /concelier/observations

Headers

Header Required Description
X-Stella-Tenant Yes Tenant identifier for multi-tenant isolation.
X-Stella-Request-Id No Optional correlation ID for distributed tracing.

Query Parameters

Parameter Type Description
advisoryKey string Filter by advisory key (CVE, GHSA, etc.).
purl string[] Filter by Package URLs (repeatable).
source string Filter by upstream source.
format string Filter by content format (OSV, GHSA, etc.).
limit integer Maximum observations to return (default: 50, max: 200).
cursor string Opaque cursor for pagination.

Response (200)

{
  "observations": [
    {
      "id": "obs:nvd:CVE-2024-1234:2025-11-20T10:30:00Z",
      "tenant": "acme",
      "advisoryKey": "CVE-2024-1234",
      "aliases": ["CVE-2024-1234", "GHSA-abcd-efgh-ijkl"],
      "source": "nvd",
      "format": "OSV",
      "purls": ["pkg:npm/vulnerable-package@1.0.0"],
      "cpes": ["cpe:2.3:a:example:vulnerable-package:1.0.0:*:*:*:*:node.js:*:*"],
      "severity": {
        "type": "CVSS_V3",
        "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
        "baseScore": 9.8,
        "label": "critical"
      },
      "summary": "Remote code execution vulnerability in vulnerable-package",
      "publishedAt": "2024-06-15T12:00:00Z",
      "modifiedAt": "2024-06-20T08:00:00Z",
      "observedAt": "2025-11-20T10:30:00Z",
      "provenance": {
        "connectorId": "nvd-osv-connector",
        "retrievedAt": "2025-11-20T10:30:00Z",
        "contentHash": "sha256:a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
        "signaturePresent": false,
        "signatureVerified": false
      },
      "raw": {
        "id": "CVE-2024-1234",
        "modified": "2024-06-20T08:00:00Z",
        "published": "2024-06-15T12:00:00Z",
        "aliases": ["CVE-2024-1234"],
        "summary": "Remote code execution vulnerability in vulnerable-package",
        "details": "A critical vulnerability exists in vulnerable-package versions prior to 2.0.0...",
        "severity": [
          {
            "type": "CVSS_V3",
            "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
          }
        ],
        "affected": [
          {
            "package": {
              "ecosystem": "npm",
              "name": "vulnerable-package"
            },
            "ranges": [
              {
                "type": "SEMVER",
                "events": [
                  {"introduced": "0"},
                  {"fixed": "2.0.0"}
                ]
              }
            ]
          }
        ],
        "references": [
          {
            "type": "ADVISORY",
            "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-1234"
          }
        ]
      }
    },
    {
      "id": "obs:github:GHSA-abcd-efgh-ijkl:2025-11-18T14:00:00Z",
      "tenant": "acme",
      "advisoryKey": "CVE-2024-1234",
      "aliases": ["CVE-2024-1234", "GHSA-abcd-efgh-ijkl"],
      "source": "github",
      "format": "GHSA",
      "purls": ["pkg:npm/vulnerable-package@1.0.0"],
      "cpes": [],
      "severity": {
        "type": "CVSS_V3",
        "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
        "baseScore": 9.8,
        "label": "critical"
      },
      "summary": "Critical RCE in vulnerable-package",
      "publishedAt": "2024-06-15T14:00:00Z",
      "modifiedAt": "2024-06-18T10:00:00Z",
      "observedAt": "2025-11-18T14:00:00Z",
      "provenance": {
        "connectorId": "github-advisory-connector",
        "retrievedAt": "2025-11-18T14:00:00Z",
        "contentHash": "sha256:b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456ab",
        "signaturePresent": true,
        "signatureVerified": true
      },
      "raw": {
        "id": "GHSA-abcd-efgh-ijkl",
        "aliases": ["CVE-2024-1234"],
        "summary": "Critical RCE in vulnerable-package",
        "severity": [{"type": "CVSS_V3", "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"}],
        "database_specific": {
          "github_reviewed": true,
          "github_reviewed_at": "2024-06-15T14:00:00Z"
        }
      }
    }
  ],
  "linkset": {
    "aliases": ["CVE-2024-1234", "GHSA-abcd-efgh-ijkl"],
    "purls": ["pkg:npm/vulnerable-package@1.0.0"],
    "cpes": ["cpe:2.3:a:example:vulnerable-package:1.0.0:*:*:*:*:node.js:*:*"],
    "references": [
      {"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-1234", "type": "ADVISORY"},
      {"url": "https://github.com/advisories/GHSA-abcd-efgh-ijkl", "type": "ADVISORY"}
    ],
    "scopes": ["npm"],
    "relationships": [],
    "confidence": 0.95,
    "conflicts": []
  },
  "nextCursor": null,
  "hasMore": false,
  "freshness": null
}

Response with Conflicts

When observations from different sources disagree:

{
  "observations": [
    {
      "id": "obs:nvd:CVE-2024-5678:2025-11-20T10:30:00Z",
      "advisoryKey": "CVE-2024-5678",
      "source": "nvd",
      "severity": {
        "type": "CVSS_V3",
        "baseScore": 9.8,
        "label": "critical"
      },
      "observedAt": "2025-11-20T10:30:00Z"
    },
    {
      "id": "obs:vendor:CVE-2024-5678:2025-11-22T08:00:00Z",
      "advisoryKey": "CVE-2024-5678",
      "source": "vendor-security",
      "severity": {
        "type": "CVSS_V3",
        "baseScore": 7.5,
        "label": "high"
      },
      "observedAt": "2025-11-22T08:00:00Z"
    }
  ],
  "linkset": {
    "aliases": ["CVE-2024-5678"],
    "purls": ["pkg:npm/another-package@3.0.0"],
    "cpes": [],
    "confidence": 0.72,
    "conflicts": [
      {
        "field": "severity",
        "code": "severity-mismatch",
        "observedValues": [
          {"source": "nvd", "value": "critical", "observedAt": "2025-11-20T10:30:00Z"},
          {"source": "vendor-security", "value": "high", "observedAt": "2025-11-22T08:00:00Z"}
        ],
        "reason": "Sources disagree on severity classification: nvd reports critical (9.8), vendor-security reports high (7.5)"
      }
    ]
  },
  "nextCursor": null,
  "hasMore": false
}

Errors

Status Code Description
400 ERR_VALIDATION_FAILED Invalid query parameters.
400 ERR_INVALID_CURSOR Malformed or expired cursor.
401 ERR_UNAUTHORIZED Missing or invalid authentication.
403 ERR_FORBIDDEN Tenant access denied.
404 ERR_RESOURCE_NOT_FOUND No observations found for advisory.

Error Response Example

{
  "type": "https://stellaops.io/errors/validation-failed",
  "title": "Validation Failed",
  "status": 400,
  "detail": "The 'advisoryKey' parameter is required when 'source' is specified.",
  "instance": "/advisories/observations",
  "traceId": "trace-id-xyz789",
  "error": {
    "code": "ERR_VALIDATION_FAILED",
    "message": "Missing required parameter.",
    "target": "advisoryKey",
    "innerErrors": [
      {
        "field": "advisoryKey",
        "code": "REQUIRED_WHEN",
        "message": "advisoryKey is required when source is specified"
      }
    ]
  }
}

Observation Lifecycle

  1. Ingested: Raw advisory data retrieved from upstream source.
  2. Validated: Schema validated against content format (OSV, GHSA, etc.).
  3. Stored: Immutable observation record created with provenance.
  4. Linked: Observation contributes to linkset aggregation.

Determinism & Ordering

  • Observations are ordered by observedAt desc, then source asc, then id asc.
  • The same query with identical parameters returns identical results.
  • Cursor-based pagination ensures stable iteration even as new data arrives.

Notes

  • Observations are immutable; updates from upstream create new observation records.
  • The raw field contains the unmodified upstream content.
  • Provenance includes connector identity and content hashes for audit.
  • Multiple observations may exist for the same advisory from different sources.
  • Conflicts are detected and surfaced in the aggregate linkset, not resolved.

Changelog

  • 2025-12-06: Added curated examples with conflict scenarios (CONCELIER-WEB-OAS-62-001).
  • 2025-11-17: LNM v1 specification frozen.