# v1.9.4 calibration report — hardened-adversarial validation

**Date:** 2026-05-12
**Release:** v1.9.4
**Topology under test:** v1.9.3 (frozen 2026-05-09; 9 nodes)
**Predecessor reports:**
[v1.9.0](v1.9-validation-summary.md) (original soft-corpus calibration) and
[v1.9.3](v1.9.3-calibration.md) (topology-surgery spot check).

## Headline

The v1.9.4 milestone validates the **design property** behind the
asymmetric-likelihood Bayesian layer (correlation.md §4.8.3): when
the public DNS channel reveals little, the layer must hedge —
flagging `sparse=true`, reporting wide credible intervals, and
refusing to assert high-confidence posteriors on evidence-binding-
silent nodes.

A 50-domain hardened-adversarial corpus (drawn from heavy edge-
proxied apexes, privacy-focused orgs, major financial institutions,
defense contractors, and government agencies — categories selected
for known minimal-DNS / wildcard-cert / heavily-fronted posture)
exercised the design property end-to-end.

| Metric | Result |
|---|---|
| Spot-check agreement on high-confidence posteriors | **100%** (157/157 non-sparse posteriors back the deterministic pipeline) |
| Overall sparse-flag rate | **64.0%** (288/450 node-domain observations flagged as sparse) |
| Multi-signal correlation depth | 92.0% (46/50 domains have ≥ 2 evidence bindings firing) |
| Cross-source conflicts | 0 (50/50 corpus, dampener not exercised) |
| Soft-corpus regression check | -17 high-confidence posteriors v1.9.0 → v1.9.3+ topology (expected; the `email_security_strong` split into two more-conservative nodes) |

The design property holds. The layer hedges on hardened targets
without over-claiming.

## Per-node sparse-rate trend

Sparse rate per node across three runs: v1.9.0 (original soft
corpus on the pre-split topology), v1.9.3+ (same soft corpus on
the current topology), and v1.9.4-hardened (the new 50-domain
adversarial corpus on the current topology).

```
node                                v1.9.0 sparse%  v1.9.3+ sparse%  v1.9.4-hardened sparse%
-------------------------------------------------------------------------------------------
aws_hosting                                  78.0%            78.0%                   76.0%
cdn_fronting                                 28.6%            28.6%                   40.0%
email_gateway_present                        64.8%            64.8%                   80.0%
email_security_modern_provider                 n/a           100.0%                  100.0%
email_security_policy_enforcing                n/a             8.8%                    8.0%
email_security_strong                         8.8%              n/a                     n/a
federated_identity                           74.7%            75.8%                   72.0%
google_workspace_tenant                      65.9%            67.0%                   66.0%
m365_tenant                                  33.0%            33.0%                   40.0%
okta_idp                                     95.6%            95.6%                   94.0%
```

Reading the columns:

- **v1.9.0 → v1.9.3+ on the same corpus** (no-regression check):
  sparse rates are within 1-2 percentage points on every node that
  exists in both topologies. `federated_identity` moved 74.7% →
  75.8% (+1.1pp), consistent with v1.9.3's parent-expansion making
  it slightly more conservative on GWS-only paths. No backsliding;
  no node became *less* sparse after the topology change.
- **email_security_strong (v1.9.0) split into modern_provider +
  policy_enforcing (v1.9.3+):** the original node had 8.8% sparse
  rate; the split produces `modern_provider` at 100% sparse (correct
  by design — no evidence bindings, pure CPT propagation) and
  `policy_enforcing` at 8.8% sparse (preserves the original
  evidence-driven behaviour). The 17-posterior reduction in the
  regression tripwire below is fully accounted for by this split.
- **Soft → hardened sparse-rate increases** are observable on
  `cdn_fronting` (28.6% → 40%), `email_gateway_present` (64.8% →
  80%), and `m365_tenant` (33% → 40%) — the asymmetric-likelihood
  design's headline claim in action: nodes that depend on
  enterprise-style public DNS exposure correctly back off on
  hardened targets.

## High-confidence survival ratios (soft → hardened)

The asymmetric-likelihood design's headline claim is that nodes
which *should* be hard to detect on hardened targets will back
off. The survival ratio (hardened high-conf% / soft high-conf%)
quantifies this:

```
node                                soft high-conf%   hardened high-conf%   survival ratio
-------------------------------------------------------------------------------------------
aws_hosting                                  22.0%                24.0%             1.09
cdn_fronting                                 71.4%                60.0%             0.84
email_gateway_present                        35.2%                20.0%             0.57
email_security_modern_provider                0.0%                 0.0%              n/a
email_security_policy_enforcing              69.2%                68.0%             0.98
federated_identity                           24.2%                28.0%             1.16
google_workspace_tenant                      33.0%                34.0%             1.03
m365_tenant                                  67.0%                60.0%             0.90
okta_idp                                      3.3%                 4.0%             1.21
```

Reading the ratios:

- **`email_gateway_present` survival = 0.57** is the cleanest
  demonstration of the design property. Hardened orgs do not
  publish Proofpoint / Mimecast / Barracuda MX records publicly
  (or route through them less commonly), and the Bayesian layer
  correctly retreats. A naive single-signal detector would still
  fire whenever MX records pointed somewhere; the asymmetric
  likelihood lets `email_gateway_present` go sparse.
- **`cdn_fronting` survival = 0.84** with hardened high-conf at
  60%: most hardened categories *do* front their apex with a CDN.
  CF / Akamai / Fastly are part of the hardening posture, not
  obscured by it. The layer correctly fires on the CDN that *is*
  observable while leaving everything behind it sparse.
- **`email_security_policy_enforcing` survival = 0.98** holds
  steady across soft → hardened: DMARC policy is a public TXT
  record that orgs almost always publish. The node correctly
  fires regardless of provider posture.
- **`aws_hosting`, `federated_identity`, `google_workspace_tenant`,
  `okta_idp` survival > 1.0** is *not* a bug. These ratios are
  above 1 because the hardened corpus happens to over-represent
  organizations whose hardening pattern includes those specific
  services (defense / gov on AWS; AWS over Okta in finance;
  defense contractors on federated IdP with GWS-secondary
  posture). The Bayesian layer correctly surfaces them when the
  evidence is there; survival > 1 reflects the corpus mix, not a
  layer regression. The `federated_identity` and
  `google_workspace_tenant` survivals (1.16 and 1.03 respectively)
  reflect the v1.9.4 CNAME walker change as well: the suffix-only
  walker (post-audit-fix) traverses two additional chains on
  defense-category domains that the prior split-horizon-check
  walker truncated, surfacing one additional firing per node on
  the defense category (90% sparse → 80% sparse for both nodes
  in defense).

## Per-category breakdown

The 50-domain corpus is stratified across five categories of
hardening posture (10 domains each). Each category produces a
distinctive sparse-rate fingerprint:

```
node                                   edge-proxied         privacy       financial         defense      government
(n)                                            (10)            (10)            (10)            (10)            (10)
-------------------------------------------------------------------------------------------------------------------
aws_hosting                              50% sparse      60% sparse     100% sparse      80% sparse      90% sparse
cdn_fronting                             50% sparse      70% sparse      10% sparse      60% sparse      10% sparse
email_gateway_present                    90% sparse     100% sparse      50% sparse      70% sparse      90% sparse
email_security_modern_provider          100% sparse     100% sparse     100% sparse     100% sparse     100% sparse
email_security_policy_enforcing           0% sparse      20% sparse       0% sparse      20% sparse       0% sparse
federated_identity                       60% sparse      80% sparse      50% sparse      80% sparse      90% sparse
google_workspace_tenant                  10% sparse      40% sparse     100% sparse      80% sparse     100% sparse
m365_tenant                              60% sparse      50% sparse      20% sparse      50% sparse      20% sparse
okta_idp                                 90% sparse      90% sparse      90% sparse     100% sparse     100% sparse
```

The category fingerprints map onto distinctive defensive postures:

- **Edge-proxied:** `cdn_fronting` 50% sparse (the front *is* CDN
  for these; visible) but everything else moderately hidden.
- **Privacy-focused:** `email_gateway_present` 100% sparse, GWS
  40%, federated 80% — privacy-orgs minimize SaaS verification
  surface; the layer correctly reports little.
- **Financial:** `m365_tenant` 20% sparse, `gws` 100% sparse,
  `cdn_fronting` 10% sparse, `email_gateway` 50% sparse — financial
  institutions heavily run M365 + CDN-fronted public sites;
  virtually no GWS in the sample. Bayesian layer fires high-conf
  exactly where the public signal is dense.
- **Defense:** `gws` 80%, `aws` 80%, `federated` 80% sparse —
  defense contractors expose minimal identity / cloud signals
  publicly. The layer correctly reports little. The 80% sparse
  rate on `federated_identity` and `google_workspace_tenant`
  (versus 90% before the v1.9.4 CNAME walker change) reflects two
  additional defense-category chains that the suffix-only walker
  now traverses past split-horizon hops; one additional firing
  per node moved 10pp of the category.
- **Government:** `m365` 20% sparse, `gws` 100% sparse, `cdn`
  10% sparse — federal agencies are M365-heavy and CDN-fronted;
  almost no GWS in this sample. Identical fingerprint to
  finance from the layer's perspective.

## Soft-corpus regression check (tripwire)

Re-running the original v1.9.0 91-domain soft corpus on the current
v1.9.3+ topology shows:

| Metric | v1.9.0 (original topology) | v1.9.3+ (current topology) | Delta |
|---|---|---|---|
| Total high-confidence posteriors | 313 | 296 | -17 |

The 17-posterior reduction is fully accounted for by the v1.9.3
`email_security_strong` split: the original node had 78 high-
confidence posteriors at 52.6% deterministic-pipeline agreement
(the calibration weak spot the split fixed). The split replaces
those with `modern_provider` (always sparse — counts as zero
high-confidence by definition) and `policy_enforcing` (62 high-
confidence at 100% agreement on this corpus). Net: 78 → 62, a
-16 delta concentrated entirely on the split node. The remaining
-1 reflects `federated_identity`'s parent-expansion (slightly more
conservative on GWS-only paths). **No node had its high-confidence
calibration degraded by the topology surgery.**

## Reproducibility

The hardened-adversarial corpus inclusion criteria are documented
at the top of `validation/corpus-private/v1.9.4-hardened.txt`. A
domain qualifies if it satisfies at least three of:

1. Wildcard SAN ratio ≥ 80% (most published certs are *.<apex>).
2. CNAME chain depth ≥ 3 (heavily proxied / multi-hop).
3. No public IdP metadata (no `/v2.0/.well-known/openid-configuration`).
4. ≤ 2 published DNS records beyond the apex (minimal-DNS posture).
5. Certificate validity ≤ 30 days (short-lived rotation).

Categories the corpus draws from (10 domains each): heavy
edge-proxied apexes, privacy-focused orgs, major financial
institutions, defense contractors, and major government agencies.
The selection methodology biases toward publicly-documented
postures, not corporate-secret intel — anyone with a list of
known hardened-posture orgs in each category can build a
comparable corpus.

To reproduce the public components:

```bash
# Re-run the existing analyzer against a private hardened corpus.
python -m recon_tool.cli batch validation/corpus-private/v1.9.4-hardened.txt \
    --ndjson --fusion --concurrency 6 \
    > validation/corpus-private/v1.9.4-hardened/results.ndjson

# Aggregate (anonymized; no domain names printed).
python validation/analyze_v19_4_hardened.py \
    --hardened       validation/corpus-private/v1.9.4-hardened/results.ndjson \
    --hardened-source validation/corpus-private/v1.9.4-hardened.txt \
    --soft-current   validation/runs-private/v1.9.4-soft-rerun/results.ndjson \
    --soft-original  validation/runs-private/v1.9-calibration/results.ndjson
```

The corpus file and results live under `validation/corpus-private/`
and `validation/runs-private/`, both gitignored.

## Defensive value

The v1.9.4 milestone proves something **defenders care about**:
when you harden your public-DNS footprint, recon's Bayesian layer
*correctly* tells the operator the public channel reveals little.
A defender running recon against their own hardened apex gets:

- Sparse=true on most identity / cloud / email-gateway nodes
- Wide credible intervals reporting the passive-observation
  ceiling
- High-confidence fires only on nodes whose evidence the org
  genuinely chose to expose (DMARC policy; CDN front)

The layer cannot be tricked into asserting confident answers it
doesn't have. That's the calibration discipline working as
designed.

For attackers running recon against a hardened target, the
implication is the same in the opposite direction: the layer
*will not* invent inferences from sparse data. A "tentative low,
sparse=true, interval [0.0, 0.45]" output is honest about what
public DNS does and does not say.

## What this run does NOT validate

1. **Per-vertical generalization across the long tail.** The
   50-domain corpus stratifies across 5 categories of 10 each;
   each category surfaces a distinctive fingerprint. Long-tail
   verticals (healthcare-payer, higher-ed, retail-fast-food,
   crypto-exchange) were not sampled.
2. **Adversarial DNS that explicitly tries to mislead.** The
   corpus represents *defensively-hardened* posture, not
   *actively-deceptive* posture. A domain whose owner crafts
   misleading CNAMEs to fool fingerprinting would test a different
   threat model.
3. **The v1.9.5 per-node stability criteria.** This run validates
   the design property at the *layer* level. The v1.9.5 milestone
   will apply per-node stability criteria using both the v1.9.0
   soft-corpus run and this v1.9.4 hardened run as input data.

## v2.0 implications

This milestone clears the v1.9.4 step of the v1.9.4 → v2.0
linear sequence in `docs/roadmap.md`. The asymmetric-likelihood
design property is validated. The next bridge milestone (v1.9.5)
takes the per-node firing counts from both this run and the
soft-corpus re-run as its raw inputs.

The detailed `correlation.md` failure-mode catalog
(§ 4.8.10) cross-references each category's fingerprint to
defensive guidance — "if you're worried about X being inferable
from your hardened public DNS, here's what the layer reports
and why."
