syntax = "proto3";

package worldmonitor.resilience.v1;

message DimensionFreshness {
  // Unix milliseconds when the oldest constituent signal in this
  // dimension was last observed (min fetchedAt across INDICATOR_REGISTRY
  // entries for this dimension). 0 when no signal has ever been
  // observed.
  int64 last_observed_at_ms = 1;
  // Worst staleness level across the dimension's constituent signals,
  // classified by classifyStaleness against each signal's cadence.
  // One of: "fresh", "aging", "stale". Empty string when no signals.
  string staleness = 2;
}

message ResilienceDimension {
  string id = 1;
  double score = 2;
  double coverage = 3;
  double observed_weight = 4;
  double imputed_weight = 5;
  // Four-class imputation taxonomy (Phase 1 T1.7). Empty string when the
  // dimension has any observed data. One of: "stable-absence", "unmonitored",
  // "source-failure", "not-applicable". See docs/methodology/country-resilience-index.mdx.
  string imputation_class = 6;
  // Freshness aggregated across the constituent signals of the
  // dimension. Phase 1 T1.5 of the reference-grade upgrade plan.
  // Empty `last_observed_at_ms=0` + `staleness=""` when the dimension
  // has no signals tracked in the indicator registry.
  DimensionFreshness freshness = 7;
}

message ResilienceDomain {
  string id = 1;
  double score = 2;
  double weight = 3;
  repeated ResilienceDimension dimensions = 4;
}

message ResilienceRankingItem {
  string country_code = 1;
  double overall_score = 2;
  string level = 3;
  bool low_confidence = 4;
  double overall_coverage = 5;
  bool rank_stable = 6;
}

// Phase 2 T2.1 of the country-resilience reference-grade upgrade plan.
// Three-pillar response shape that regroups the existing 5 domains into
// long-run capacity, current shock pressure, and recovery capability.
// Shipped as a shaped-but-empty payload in T2.1 (score=0, coverage=0);
// real aggregation lands in T2.3 / PR 4 of the Phase 2 rebuild.
message ResiliencePillar {
  // "structural-readiness" | "live-shock-exposure" | "recovery-capacity".
  string id = 1;
  // Pillar score in [0, 100]. 0 when shipped empty (T2.1).
  double score = 2;
  // Pillar weight in the overall combine. Per the plan: 0.40 / 0.35 / 0.25.
  double weight = 3;
  // Coverage in [0, 1]. 0 when shipped empty (T2.1).
  double coverage = 4;
  // Subset of the 5 ResilienceDomains that compose this pillar.
  repeated ResilienceDomain domains = 5;
}
