Parascope Docs

CI Criticality Scoring

Automated impact assessment based on dependencies, size, and type importance

Parascope assigns a Criticality Score (0-100) to every Configuration Item, conveying its relative importance based on downstream dependencies, relative size, and inherent type importance.

Overview

The criticality score answers: "If this CI fails, how bad is it?"

  • High scores (80-100): Core infrastructure—failure causes widespread impact
  • Medium-high scores (60-79): Important platform services and workloads
  • Medium scores (40-59): Standard workloads with moderate dependencies
  • Low scores (0-39): Leaf CIs with limited downstream impact

Scoring Formula

The current algorithm is v3, which combines three components:

Criticality Score = (
    Dependency_Score × 0.5 +       # Downstream/blast radius impact
    Size_Score × 0.2 +             # Relative size within a peer cohort
    Type_Score × 0.3               # Inherent importance by CI type
) × 100

Weight Rationale

ComponentWeightWhy
Dependency Impact50%Direct measure of blast radius—if this CI fails, how much else breaks?
Size20%A larger resource (more capacity, more workloads) within its peer group is generally more significant
Type Criticality30%Infrastructure (clusters, nodes) is inherently more critical than leaf CIs

When Size Cannot Be Measured

Many CI types have no meaningful capacity signal (a ConfigMap has no "size"). When a CI has no extractable size, the size term is dropped and the dependency and type weights are renormalized proportionally so they still sum to 1.0:

Criticality Score = (
    Dependency_Score × 0.625 +
    Type_Score × 0.375
) × 100

This ensures the absence of a size signal neither penalizes nor rewards a CI—it simply removes the term and rescales the survivors.


Component 1: Dependency Score (0.0-1.0)

Measures "how many CIs would be affected if this CI fails" using relationship graph traversal.

Algorithm

  1. Traverse relationships up to 3 levels deep
  2. Weight dependents by depth (1.0 at depth 0, 0.5 at depth 1, 0.33 at depth 2)
  3. Weight by relationship type importance
  4. Apply logarithmic normalization (diminishing returns)

Relationship Type Weights

RelationshipWeightDescription
runs_on1.0Pods running on nodes
is_contained_by0.9Resources in namespaces
manages0.85Deployments managing pods
implemented_by0.8Infrastructure implementation
member_of0.8Cluster membership
scheduled_on0.75Workloads scheduled on nodes
member_of_service0.7Component membership in system
affects0.7Vulnerability affects asset
selects0.7Services selecting pods
backs0.7Pods backing a service
member_of_product0.65System membership in domain
exposes0.65Services exposing pods
governs_ingress0.6Network policies
governs_egress0.6Network policies
depends_on0.6Service dependency
provides0.6API provision
uses0.55Resource consumption
installed_on0.55OS installed on VM/container
consumes0.55API consumption
mounts0.5Volume mounts
stores_on0.5Storage dependencies
correlates_with0.3Cross-system correlation

Unknown relationship types default to 0.4.


Component 2: Size Score (0.0-1.0)

For CI types where a meaningful size can be extracted (nodes, VMs, pods, storage pools, databases, etc.), the size score is the CI's percentile rank within its size cohort — a group of comparable types (its "type family"). A node in the top decile of its cluster scores near 1.0; a small one scores near 0.0.

CI types with no extractable size omit this component entirely (see When Size Cannot Be Measured).


Component 3: Type Criticality (0.0-1.0)

Base criticality tier by CI type.

ScoreTierExample CI Types
0.95Infrastructurekubernetes.node, kubernetes.cluster, proxmox.node, proxmox.cluster, openstack.hypervisor, ceph.cluster, ceph.monitor, postgresql.server, aws.account
0.70Platformkubernetes.deployment, kubernetes.statefulset, kubernetes.daemonset, ceph.pool, ceph.osd, proxmox.storage, netbox.device, postgresql.database
0.45Workloadkubernetes.pod, kubernetes.service, proxmox.vm, proxmox.container, openstack.instance, os.linux
0.30Configurationkubernetes.configmap, kubernetes.namespace, kubernetes.networkpolicy, openstack.port, netbox.interface

Unknown types default to 0.5.


Display Tiers

Score RangeTierColor
80-100CriticalRed
60-79HighOrange
40-59MediumYellow
0-39LowGreen

API Endpoints

Get CI Criticality Score

GET /api/v1/criticality/ci/{ci_id}

Response:

{
  "ci_id": "550e8400-e29b-41d4-a716-446655440000",
  "score": 78,
  "tier": "High",
  "color": "orange",
  "breakdown": {
    "dependency_score": 0.82,
    "size_score": 0.65,
    "size_percentile": 0.65,
    "type_score": 0.7
  },
  "metadata": {
    "direct_dependents": 5,
    "transitive_dependents": 23,
    "type_family": "controller"
  },
  "calculated_at": "2026-06-10T10:30:00Z",
  "algorithm_version": "v3"
}

When a CI has no measurable size, size_score and size_percentile are null and the renormalized two-component formula is used.

Recalculate Scores

POST /api/v1/criticality/recalculate

Request Body:

{
  "ci_ids": ["uuid1", "uuid2"],
  "force": false
}
  • ci_ids is optional — omit it (or send null) to recalculate all active CIs.
  • force: true recalculates even if scores are fresh.

When you pass an explicit ci_ids list, those CIs are scored synchronously and the response reports how many were updated:

{
  "status": "completed",
  "cis_processed": 12,
  "cis_updated": 12,
  "errors": [],
  "duration_seconds": 0.4
}

When ci_ids is omitted, the full estate is queued for the background scorer instead of being computed inline (so the request returns promptly on large tenants). The response reports how many CIs were queued; scores converge within the next scoring cycle:

{
  "status": "queued",
  "cis_processed": 819,
  "cis_updated": 0,
  "errors": [],
  "duration_seconds": 0.05
}

Get Criticality Statistics

GET /api/v1/criticality/stats

Returns distribution summary across all CIs.

Bulk Get Scores

POST /api/v1/criticality/bulk

The request body is a JSON array of CI ID strings. The response is a map from CI ID to its criticality summary.

Request Body:

["uuid1", "uuid2", "uuid3"]

Response:

{
  "uuid1": { "score": 78, "tier": "High", "color": "orange" },
  "uuid2": { "score": 24, "tier": "Low", "color": "green" }
}

CI List Integration

Include criticality in CI list queries:

GET /api/v1/configuration-items?include_criticality=true

Each CI in the response includes:

{
  "ci_id": "...",
  "name": "pve",
  "ci_type": "proxmox.node",
  "criticality": {
    "score": 92,
    "tier": "Critical",
    "color": "red"
  }
}

Sorting by Criticality

GET /api/v1/configuration-items?include_criticality=true&sort_by=criticality_score&sort_order=desc

Automatic Scoring

Scores recalculate automatically when infrastructure relationships change. New CIs are scored within minutes of discovery. Scores are also re-derived automatically when the scoring algorithm version changes—a CI whose stored algorithm_version differs from the current version is re-scored on its next pass.

Manual Recalculation

For immediate recalculation, use the API:

# Recalculate all CIs
curl -X POST https://your-company.parascope.io/api/v1/criticality/recalculate

# Recalculate specific CIs
curl -X POST https://your-company.parascope.io/api/v1/criticality/recalculate \
  -H "Content-Type: application/json" \
  -d '{"ci_ids": ["uuid1", "uuid2"]}'

Examples

Each example is reproducible from the v3 formula round((dependency × 0.5 + size × 0.2 + type × 0.3) × 100).

High Criticality CI (Proxmox Node)

Name: pve
Type: proxmox.node
Score: 90 (Critical)

Breakdown:
- Dependency: 0.89 (63 transitive dependents - all VMs/containers)
- Size: 0.85 (large node, high percentile in its cohort)
- Type: 0.95 (infrastructure tier)

0.89 × 0.5 + 0.85 × 0.2 + 0.95 × 0.3 = 0.900 → 90

Medium Criticality CI (Kubernetes Deployment)

Name: api-server
Type: kubernetes.deployment

This type has no measurable size, so the renormalized
two-component formula is used:
Score: 47 (Medium)

Breakdown:
- Dependency: 0.40 (manages several pods)
- Size: null (no capacity signal)
- Type: 0.70 (platform tier)

0.40 × 0.625 + 0.70 × 0.375 = 0.4625 → 47

Low Criticality CI (ConfigMap)

Name: app-config
Type: kubernetes.configmap

ConfigMaps have no measurable size, so the renormalized
two-component formula is used:
Score: 24 (Low)

Breakdown:
- Dependency: 0.20 (referenced by 2 pods)
- Size: null (no capacity signal)
- Type: 0.30 (configuration tier)

0.20 × 0.625 + 0.30 × 0.375 = 0.2375 → 24

Changelog

  • v3 (current): Reintroduced a real, writer-implemented size component (per-cohort percentile). Weights rebalanced to dependency 0.5 / size 0.2 / type 0.3, with size-absent CIs renormalized to 0.625 / 0.375.
  • v2: Removed a placeholder size component that was never actually computed and renormalized the remaining weights.
  • v1: Original two-signal model (dependency and type) with a non-functional size term.