Feed Snapshot Freeze/Staleness Thresholds (SP6)

Status: Draft · Date: 2025-12-04 Scope: Codify feed snapshot governance including freshness budgets, staleness thresholds, freeze procedures, and validation checks.

Objectives

Freshness Budgets

Feed Types

Feed TypeSourceMax AgeStaleness ThresholdCritical Threshold
NVDNIST NVD24 hours48 hours7 days
OSVOSV.dev12 hours24 hours3 days
GHSAGitHub12 hours24 hours3 days
AlpineAlpine SecDB24 hours48 hours7 days
DebianDebian Security Tracker24 hours48 hours7 days
RHELRed Hat OVAL24 hours72 hours7 days
UbuntuUbuntu CVE Tracker24 hours48 hours7 days

Definitions

Snapshot States

┌─────────────┐
│   SYNCING   │ ──────────────────────────────────┐
└─────────────┘                                   │
       │                                          │
       ▼                                          ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│    FRESH    │ ──► │    STALE    │ ──► │  CRITICAL   │
└─────────────┘     └─────────────┘     └─────────────┘
       │                   │                   │
       ▼                   ▼                   ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   FROZEN    │     │   FROZEN    │     │   FROZEN    │
│   (fresh)   │     │   (stale)   │     │  (critical) │
└─────────────┘     └─────────────┘     └─────────────┘

State Transitions

Current StateTriggerNew StateAction
SYNCINGSync completeFRESHRecord snapshot hash
FRESHMax age exceededSTALEEmit warning
STALEStaleness threshold exceededCRITICALBlock scans
CRITICALManual overrideCRITICAL (override)Log override
AnyFreeze commandFROZENLock snapshot
FROZENThaw commandPrevious stateUnlock snapshot

Snapshot Schema

{
  "id": "nvd-2025-12-04T00-00-00Z",
  "feed": "nvd",
  "source": "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz",
  "syncedAt": "2025-12-04T00:00:00Z",
  "hash": {
    "blake3": "...",
    "sha256": "..."
  },
  "state": "fresh",
  "advisoryCount": 250000,
  "lastModified": "2025-12-03T23:45:00Z",
  "frozen": false,
  "frozenAt": null,
  "frozenBy": null,
  "thresholds": {
    "maxAge": "PT24H",
    "staleness": "PT48H",
    "critical": "P7D"
  }
}

Freeze Procedures

Manual Freeze

# Freeze current snapshot for reproducible scans
stellaops feed freeze --feed nvd --reason "Audit baseline 2025-Q4"

# Freeze with specific snapshot
stellaops feed freeze --feed nvd --snapshot-id nvd-2025-12-04T00-00-00Z

# List frozen snapshots
stellaops feed list --frozen

Automatic Freeze (Replay Mode)

When recording a scan for replay:

  1. Scanner captures current snapshot IDs for all feeds
  2. Snapshot hashes recorded in replay manifest
  3. Replay execution uses frozen snapshots from manifest
{
  "replay": {
    "feeds": {
      "nvd": {
        "snapshotId": "nvd-2025-12-04T00-00-00Z",
        "hash": "b3:...",
        "state": "frozen"
      },
      "osv": {
        "snapshotId": "osv-2025-12-04T00-00-00Z",
        "hash": "b3:...",
        "state": "frozen"
      }
    }
  }
}

Thaw Procedures

# Thaw a frozen snapshot (resume normal sync)
stellaops feed thaw --feed nvd --snapshot-id nvd-2025-12-04T00-00-00Z

# Force thaw all frozen snapshots
stellaops feed thaw --all --force

Validation Checks

Pre-Scan Validation

# scripts/scanner/validate_feeds.py
def validate_feed_freshness(feed_states: dict) -> ValidationResult:
    errors = []
    warnings = []

    for feed, state in feed_states.items():
        age = datetime.utcnow() - state['syncedAt']
        thresholds = state['thresholds']

        if age > parse_duration(thresholds['critical']):
            if not state.get('override'):
                errors.append(f"{feed}: Critical staleness ({age})")
        elif age > parse_duration(thresholds['staleness']):
            warnings.append(f"{feed}: Stale ({age})")
        elif age > parse_duration(thresholds['maxAge']):
            warnings.append(f"{feed}: Approaching staleness ({age})")

    return ValidationResult(
        valid=len(errors) == 0,
        errors=errors,
        warnings=warnings
    )

Scan Output Metadata

{
  "scan": {
    "id": "scan-12345",
    "feedState": {
      "nvd": {
        "snapshotId": "nvd-2025-12-04T00-00-00Z",
        "state": "fresh",
        "age": "PT12H",
        "hash": "b3:..."
      },
      "osv": {
        "snapshotId": "osv-2025-12-04T00-00-00Z",
        "state": "stale",
        "age": "PT36H",
        "hash": "b3:...",
        "warning": "Feed approaching staleness threshold"
      }
    }
  }
}

API Endpoints

Feed Status

GET /api/v1/feeds/status

Response:

{
  "feeds": {
    "nvd": {
      "state": "fresh",
      "snapshotId": "nvd-2025-12-04T00-00-00Z",
      "syncedAt": "2025-12-04T00:00:00Z",
      "age": "PT12H",
      "frozen": false,
      "thresholds": {
        "maxAge": "PT24H",
        "staleness": "PT48H",
        "critical": "P7D"
      }
    }
  }
}

Freeze Feed

POST /api/v1/feeds/{feed}/freeze
Content-Type: application/json

{
  "snapshotId": "nvd-2025-12-04T00-00-00Z",
  "reason": "Audit baseline"
}

Override Staleness

POST /api/v1/feeds/{feed}/override
Content-Type: application/json

{
  "snapshotId": "nvd-2025-12-04T00-00-00Z",
  "reason": "Emergency scan required",
  "approvedBy": "security-admin@example.com",
  "expiresAt": "2025-12-05T00:00:00Z"
}

Alerting

Alert Conditions

ConditionSeverityAction
Feed sync failedWarningRetry with backoff
Feed approaching stalenessInfoLog, notify ops
Feed staleWarningNotify ops, scan warnings
Feed criticalCriticalBlock scans, page on-call
Feed frozen > 30 daysWarningReview freeze necessity

Alert Payload

{
  "alert": {
    "type": "feed_staleness",
    "feed": "nvd",
    "severity": "warning",
    "snapshotId": "nvd-2025-12-04T00-00-00Z",
    "age": "PT50H",
    "threshold": "PT48H",
    "message": "NVD feed exceeds staleness threshold (50h > 48h)",
    "timestamp": "2025-12-06T02:00:00Z"
  }
}

Determinism Integration

Replay Requirements

For deterministic replay:

  1. All feeds MUST be frozen at recorded state
  2. Snapshot hashes MUST match manifest
  3. No network fetch during replay
  4. Staleness validation skipped (uses recorded state)

Validation Script

#!/bin/bash
# scripts/scanner/verify_feed_hashes.sh

MANIFEST="replay-manifest.json"

for feed in $(jq -r '.replay.feeds | keys[]' "${MANIFEST}"); do
    expected_hash=$(jq -r ".replay.feeds.${feed}.hash" "${MANIFEST}")
    snapshot_id=$(jq -r ".replay.feeds.${feed}.snapshotId" "${MANIFEST}")

    actual_hash=$(stellaops feed hash --snapshot-id "${snapshot_id}")

    if [[ "${actual_hash}" != "${expected_hash}" ]]; then
        echo "FAIL: ${feed} snapshot hash mismatch"
        echo "  expected: ${expected_hash}"
        echo "  actual:   ${actual_hash}"
        exit 1
    fi
    echo "PASS: ${feed} snapshot ${snapshot_id}"
done