Definition and Overview
Signal Plurality is a hard-enforced axiom within the NABLA Infinity epistemic framework requiring a minimum of two independent signals before any belief can be formed, any claim accepted, or any decision made. Single-source claims are insufficient regardless of source credibility, urgency, or authority level. This axiom prevents single points of epistemic failure and ensures all platform knowledge has corroborating evidence from genuinely independent origins.
The axiom addresses a fundamental vulnerability in knowledge systems: dependence on single sources creates catastrophic failure modes. A single compromised source, a single biased assessment, or a single misconfigured sensor can propagate incorrect beliefs throughout the system if there is no requirement for independent corroboration. Signal Plurality transforms this single-point-of-failure pattern into a distributed verification model where every belief requires at least two independent supporting signals.
Signal Plurality is more rigorous than simple "second opinion" requirements found in traditional decision-making frameworks. The axiom requires not just multiple signals but genuinely independent signals -- signals from sources that do not share common upstream dependencies, methodologies, or data feeds. Two signals derived from the same underlying data source count as one signal, regardless of how differently they are presented. This independence requirement prevents the illusion of plurality where multiple nominally different sources all trace back to a single origin.
Within the Prismatic Platform, Signal Plurality is enforced at the E2 level (block and rejection). Violations are not warnings -- they are hard blocks that prevent the violating claim from entering the belief system. This enforcement applies across all platform systems: OSINT intelligence fusion, EASM security ratings, Color Team assessments, and quality evaluations.
Historical Context and Motivation
The Signal Plurality axiom draws from multiple intellectual traditions. In intelligence analysis, the principle of "multi-source intelligence" (MULTI-INT) has been practiced since at least World War II, where signals intelligence (SIGINT), human intelligence (HUMINT), and imagery intelligence (IMINT) were cross-referenced to validate assessments. The failure to enforce this principle has led to documented intelligence failures, most notably the reliance on single-source intelligence in the lead-up to the Iraq War (2003), where the "Curveball" source provided uncorroborated information that shaped policy.
In scientific methodology, the requirement for independent replication serves the same function. A scientific claim is not accepted based on a single experiment; it requires independent replication by separate researchers using different methodologies. The replication crisis in social science (2010s) demonstrated what happens when this standard is relaxed.
In distributed systems engineering, the concept of quorum consensus (requiring agreement from multiple nodes before accepting a write) is the technical analog of Signal Plurality. Systems like Raft and Paxos require majority agreement precisely because individual nodes can fail, be partitioned, or return stale data.
The Prismatic Platform's adoption of Signal Plurality as a hard axiom reflects a recognition that automated systems face the same epistemic risks as human intelligence analysts and distributed databases. When the platform assesses a security posture, classifies a threat, or evaluates code quality, the assessment is only as reliable as the evidence supporting it. Single-source evidence, no matter how authoritative it appears, leaves the assessment vulnerable to source failure.
Technical Deep Dive
Axiom Specification
Signal Plurality is one of seven non-negotiable axioms in the NABLA Infinity framework:
| Property | Value |
|---|---|
| Axiom Number | 1 (Signal Plurality) |
| Enforcement | HARD -- cannot be bypassed or overridden |
| Minimum Signals | 2 independent sources |
| Violation Response | E2 BLOCK -- immediate rejection |
| Override Authority | None -- no authority level can bypass |
| Scope | All beliefs, claims, and decisions platform-wide |
Independence Verification
Determining signal independence requires analysis of source provenance. Two signals are independent if and only if they have different origins, no shared upstream sources, and different collection methodologies:
defmodule Prismatic.Epistemic.SignalPlurality do
@moduledoc """
Enforces the Signal Plurality axiom: minimum 2 independent signals
for any belief. Hard enforcement with E2 block on violation.
## Independence Criteria
Two signals are considered independent when:
1. They originate from different sources
2. They share no upstream data dependencies
3. They use different collection methodologies
4. They belong to different independence classes
## Enforcement
Violations result in immediate E2 BLOCK. No authority level
can bypass this axiom. Claims that fail plurality checking
are rejected and cannot enter the belief system.
"""
@type signal :: %{
source: String.t(),
content: term(),
timestamp: DateTime.t(),
confidence: float(),
provenance: provenance()
}
@type provenance :: %{
origin: String.t(),
methodology: String.t(),
upstream_sources: [String.t()],
collection_method: atom(),
independence_class: String.t()
}
@type plurality_result ::
{:ok, :plural, [signal()]}
| {:error, :insufficient_plurality, String.t()}
@spec verify_plurality([signal()]) :: plurality_result()
def verify_plurality(signals) when length(signals) < 2 do
{:error, :insufficient_plurality,
"Only #{length()} signal(s) provided. Minimum 2 independent signals required."}
end
def verify_plurality(signals) do
independent_groups = group_by_independence(signals)
if map_size(independent_groups) >= 2 do
{:ok, :plural, signals}
else
{:error, :insufficient_plurality,
"#{length()} signals found but only #{map_size()} " <>
"independent source(s). Signals share upstream dependencies."}
end
end
@spec are_independent?(signal(), signal()) :: boolean()
def are_independent?(signal_a, signal_b) do
prov_a = signal_a.provenance
prov_b = signal_b.provenance
# Different origins
prov_a.origin != prov_b.origin and
# No shared upstream sources
MapSet.disjoint?(
MapSet.new(prov_a.upstream_sources),
MapSet.new(prov_b.upstream_sources)
) and
# Different collection methodologies
prov_a.methodology != prov_b.methodology
end
defp group_by_independence(signals) do
signals
|> Enum.group_by(fn signal ->
signal.provenance.independence_class
end)
end
endEnforcement Architecture
Platform-Wide Enforcement Points
Signal Plurality is enforced at every point where beliefs or claims are formed:
| System | Enforcement Point | Signals Required |
|---|---|---|
| Intelligence Fusion | OSINT assessment formation | 2+ OSINT providers |
| Security Ratings | Per-dimension scoring | 2+ evidence sources per dimension |
| Color Teams | Red Team finding validation | 2+ attack vector confirmations |
| Blue Team | Defensive posture assessment | 2+ monitoring signals |
| Quality Assessment | Quality domain scoring | 2+ verification tools |
| Threat Intelligence | Threat indicator acceptance | 2+ threat feeds |
| Compliance Assessment | Compliance finding validation | 2+ compliance checks |
Axiom Enforcer Integration
Signal Plurality enforcement integrates with the broader NABLA axiom checking system:
defmodule Prismatic.Epistemic.AxiomEnforcer do
@moduledoc """
Enforces all NABLA Infinity axioms with appropriate violation levels.
Signal Plurality is Axiom 1 with E2 (hard block) enforcement.
## Enforcement Levels
- E1: Warning + correction request (soft axioms)
- E2: BLOCK + rejection (hard axioms including Signal Plurality)
- E3: HALT + review required (Trinity Gate failures)
- E4: Investigation + audit (multiple axiom violations)
"""
require Logger
@type enforcement_level :: :e1_warning | :e2_block | :e3_halt | :e4_investigation
@axioms [
{:signal_plurality, :hard, :e2_block},
{:contradiction_preservation, :hard, :e2_block},
{:absence_informative, :soft, :e1_warning},
{:time_decay, :hard, :e2_block},
{:unknown_valid, :hard, :e2_block},
{:source_independence, :soft, :e1_warning},
{:provenance_mandatory, :hard, :e2_block}
]
@spec enforce_all([signal()], map()) :: {:ok, map()} | {:error, enforcement_level(), String.t()}
def enforce_all(signals, claim) do
Enum.reduce_while(@axioms, {:ok, claim}, fn {axiom, _hardness, level}, {:ok, acc} ->
case check_axiom(axiom, signals, acc) do
:ok ->
{:cont, {:ok, acc}}
{:violation, reason} ->
Logger.error("NABLA Axiom violation: #{} - #{}")
:telemetry.execute(
[:prismatic, :epistemic, :axiom_violation],
%{count: 1},
%{axiom: axiom, level: level}
)
{:halt, {:error, level, "#{}: #{}"}}
end
end)
end
defp check_axiom(:signal_plurality, signals, _claim) do
case Prismatic.Epistemic.SignalPlurality.verify_plurality(signals) do
{:ok, :plural, _} -> :ok
{:error, :insufficient_plurality, reason} -> {:violation, reason}
end
end
defp check_axiom(:provenance_mandatory, signals, _claim) do
missing = Enum.filter(signals, fn s -> is_nil(s.provenance) end)
if Enum.empty?(missing), do: :ok, else: {:violation, "#{length()} signals lack provenance"}
end
defp check_axiom(:contradiction_preservation, signals, _claim) do
# Contradictions between signals must be preserved, not resolved
:ok
end
defp check_axiom(:time_decay, signals, _claim) do
missing_timestamps = Enum.filter(signals, fn s -> is_nil(s.timestamp) end)
if Enum.empty?(missing_timestamps), do: :ok, else: {:violation, "Signals missing timestamps"}
end
defp check_axiom(:unknown_valid, _signals, _claim), do: :ok
defp check_axiom(:absence_informative, _signals, _claim), do: :ok
defp check_axiom(:source_independence, _signals, _claim), do: :ok
endSecurity Rating Enforcement
The EASM Security Rating system enforces signal plurality at the dimension level. No dimension score is accepted without at least two independent evidence sources:
defmodule PrismaticPerimeter.Rating.PluralityEnforcer do
@moduledoc """
Enforces signal plurality for each security rating dimension.
No dimension score is accepted without at least 2 independent
evidence sources. This prevents single-tool bias from distorting
security ratings.
## Rating Dimensions
Each dimension (network security, application security, DNS health,
TLS configuration, etc.) must have evidence from at least two
independent sources before a score can be assigned.
"""
@type dimension :: atom()
@type dimension_score :: %{
value: float(),
evidence: [evidence()],
confidence: float()
}
@type evidence :: %{source: String.t(), data: term(), timestamp: DateTime.t()}
@spec enforce_dimension_plurality(%{dimension() => dimension_score()}) ::
{:ok, %{dimension() => dimension_score()}} | {:error, [dimension()]}
def enforce_dimension_plurality(dimension_scores) do
insufficient =
dimension_scores
|> Enum.filter(fn {_dim, score} ->
independent_sources = count_independent_sources(score.evidence)
independent_sources < 2
end)
|> Enum.map(fn {dim, _} -> dim end)
case insufficient do
[] -> {:ok, dimension_scores}
dims -> {:error, dims}
end
end
@spec count_independent_sources([evidence()]) :: non_neg_integer()
defp count_independent_sources(evidence) do
evidence
|> Enum.map(& &1.source)
|> Enum.uniq()
|> length()
end
endSignal Quality Weighting
Not all signals carry equal weight. While plurality requires at least two signals, the system weights signals based on quality factors. This ensures that while the minimum of two independent signals is always enforced, the resulting belief confidence reflects the quality of the contributing signals:
defmodule Prismatic.Epistemic.SignalWeighting do
@moduledoc """
Weights signals based on quality factors while maintaining
the hard minimum of 2 independent signals for plurality.
## Weighting Factors
- Freshness: Recent signals carry more weight (time decay)
- Source reliability: Historically accurate sources weight higher
- Methodology rigor: Formal verification > heuristic analysis
- Corroboration count: More corroborating signals increase confidence
"""
@type quality_factors :: %{
freshness: float(),
source_reliability: float(),
methodology_rigor: float(),
corroboration_count: non_neg_integer()
}
@spec weighted_confidence([signal()]) :: float()
def weighted_confidence(signals) do
total_weight =
signals
|> Enum.map(&signal_weight/1)
|> Enum.sum()
weighted_sum =
signals
|> Enum.map(fn s -> s.confidence * signal_weight(s) end)
|> Enum.sum()
weighted_sum / max(total_weight, 1.0)
end
@spec signal_weight(signal()) :: float()
defp signal_weight(signal) do
freshness = calculate_freshness(signal.timestamp)
reliability = signal.provenance |> Map.get(:source_reliability, 0.5)
freshness * 0.4 + reliability * 0.6
end
@spec calculate_freshness(DateTime.t()) :: float()
defp calculate_freshness(timestamp) do
age_hours = DateTime.diff(DateTime.utc_now(), timestamp, :hour)
cond do
age_hours < 1 -> 1.0
age_hours < 24 -> 0.9
age_hours < 168 -> 0.7
age_hours < 720 -> 0.4
true -> 0.1
end
end
endContradiction Handling with Plural Signals
When plural signals contradict each other, the Contradiction Preservation axiom takes precedence. Contradictions between valid signals are preserved as informative data points rather than being resolved by discarding one signal:
defmodule Prismatic.Epistemic.ContradictionHandler do
@moduledoc """
Handles contradictions between plural signals.
Contradictions are preserved, not resolved by discarding one signal.
The existence of a contradiction is itself a signal that
warrants investigation.
"""
@type contradiction :: %{
signal_a: signal(),
signal_b: signal(),
description: String.t(),
detected_at: DateTime.t()
}
@spec detect_contradictions([signal()]) :: {:ok, :no_contradictions} | {:contradiction, [contradiction()]}
def detect_contradictions(signals) do
pairs = for a <- signals, b <- signals, a.source != b.source, do: {a, b}
contradictions =
pairs
|> Enum.filter(fn {a, b} -> contradicts?(a.content, b.content) end)
|> Enum.map(fn {a, b} ->
%{
signal_a: a,
signal_b: b,
description:
"Signals from #{..} and #{..} contradict. " <>
"Both preserved per Contradiction Preservation axiom.",
detected_at: DateTime.utc_now()
}
end)
|> Enum.uniq_by(fn c -> {c.signal_a.source, c.signal_b.source} end)
case contradictions do
[] -> {:ok, :no_contradictions}
found -> {:contradiction, found}
end
end
defp contradicts?(content_a, content_b) do
# Domain-specific contradiction detection
# For example, one source says port 443 is open, another says it's closed
content_a != content_b and covers_same_domain?(content_a, content_b)
end
defp covers_same_domain?(a, b) do
Map.keys(a) -- Map.keys(b) == [] or Map.keys(b) -- Map.keys(a) == []
end
endUsage Examples
Checking Signal Plurality
# Verify plurality before forming a belief about a domain's security posture
signals = [
%{
source: "shodan",
content: %{ports: [80, 443]},
timestamp: DateTime.utc_now(),
confidence: 0.9,
provenance: %{
origin: "shodan",
methodology: "active_scanning",
upstream_sources: ["shodan_crawl_db"],
collection_method: :active_scan,
independence_class: "shodan"
}
},
%{
source: "censys",
content: %{ports: [80, 443, 8080]},
timestamp: DateTime.utc_now(),
confidence: 0.85,
provenance: %{
origin: "censys",
methodology: "zmap_scanning",
upstream_sources: ["censys_universal_dataset"],
collection_method: :active_scan,
independence_class: "censys"
}
}
]
case Prismatic.Epistemic.SignalPlurality.verify_plurality(signals) do
{:ok, :plural, verified_signals} ->
# Safe to form belief - plurality satisfied
form_belief(verified_signals)
{:error, :insufficient_plurality, reason} ->
# BLOCKED - cannot proceed
Logger.error("Signal Plurality violation: #{}")
endCommon Integration Patterns
| Pattern | Implementation | Example |
|---|---|---|
| OSINT Fusion | Multiple provider queries | Shodan + Censys for port scanning |
| Certificate Validation | Multiple CT log queries | CT transparency + direct SSL scan |
| DNS Verification | Multiple resolver queries | Public DNS + authoritative nameserver |
| Reputation Check | Multiple reputation databases | GreyNoise + AbuseIPDB |
| Compliance Assessment | Multiple compliance checks | NIS2 + ZKB independent assessments |
Relationship to Other NABLA Axioms
Signal Plurality does not operate in isolation. It interacts with the other six NABLA axioms in specific ways:
| Axiom | Relationship to Signal Plurality |
|---|---|
| Contradiction Preservation | When plural signals contradict, both are preserved |
| Absence Informative | Missing second signal is itself data -- investigated as potential gap |
| Time Decay | Plural signals must be temporally current; aged signals lose weight |
| Unknown Valid | "Insufficient signals" is a valid state; do not fabricate plurality |
| Source Independence | Weighting favors independent sources; shared upstream degrades confidence |
| Provenance Mandatory | Independence verification requires provenance; signals without it are rejected |
Best Practices
Design Data Collection for Plurality from the Start: Do not build single-source systems and try to add plurality later. Multiple independent sources should be the default collection pattern.
Verify Independence Rigorously: Two APIs from the same vendor are not independent. Two analyses of the same dataset are not independent. Independence requires genuinely separate data origins.
Document Provenance for All Signals: Without provenance, independence cannot be verified. Every signal entering the system must carry its origin, methodology, and upstream dependencies.
Handle the Cost of Plurality Explicitly: Querying multiple sources takes more time and resources. Design systems with appropriate concurrency and timeout handling for plural collection.
Do Not Weaken Plurality Requirements Under Pressure: The axiom is hard-enforced precisely because pressure situations are when single-source errors are most dangerous.
Common Pitfalls
-
Confusing quantity with plurality: Ten signals from the same source still count as one independent signal. Plurality requires independent origins, not high volume.
-
Assuming API independence: Different API endpoints from the same provider share the same underlying data. They do not constitute independent signals.
-
Relaxing plurality for "trusted" sources: No source is trusted enough to bypass plurality. Even the most reliable source can be compromised, misconfigured, or outdated.
-
Treating plurality as sufficient for truth: Plurality is necessary but not sufficient. Two independent signals can both be wrong. Plurality reduces but does not eliminate epistemic risk.
-
Fabricating signals to satisfy the axiom: Generating artificial signals to meet the minimum of two violates the spirit and purpose of the axiom. The "Unknown Valid" axiom explicitly permits acknowledging insufficient evidence rather than fabricating it.
Related Concepts
- NABLA Infinity -- Parent epistemic framework defining this axiom
- Intelligence Fusion -- Multi-source correlation requiring signal plurality
- Blue Team -- Signal aggregation with plurality enforcement
- Trinity Gate -- Verification gate complementing plurality requirements
- Confidence Threshold -- Scoring system for evaluating plural signals
- Contradiction Preservation -- Handling contradictions between plural signals
- Provenance Mandatory -- Traceability requirement enabling independence verification
- Time Decay -- Temporal weighting applied to plural signals
- Shodan -- Primary discovery signal source in EASM
- Censys -- Secondary discovery signal source in EASM
- GreyNoise -- Threat context signal source complementing discovery signals
- EASM -- Security domain enforcing signal plurality per rating dimension
See Also
- Architecture -- Platform architecture overview
- Technologies -- Technology stack details
- Agents -- Agent catalog including Blue Team aggregators
Connect & Contribute
Created by Tomáš Korcak (korczis) | Open Source under GHL