Skip to content

ADR 0035 — DUT Inspection Effectiveness Validation

  • Status: Proposed (2026-05-13) — materialization tracked across SPAN-7c, SPAN-8, and SPAN-9 waves
  • Date: 2026-05-13
  • Deciders: TLSStress.Art project
  • Targets: v3.9.x — v4.x
  • Patent claim families:
  • Extends #16 (SPAN tiered ingest + cross-correlator — ADR 0024 + 0034)
  • Proposes new claim family for TLS Decryption Posture Validation via certificate-issuer differential analysis (target: provisional 2026-Q3)
  • Proposes new claim family for Fast-Path Detection in TLS-Inspecting Middleboxes via differential per-packet latency analysis combined with mid-session canary signature injection (target: provisional 2026-Q3)
  • Builds on: ADR 0024 (SPAN.Art line-rate capture), ADR 0034 (3-way fusion correlator)

Context

SPAN-3 (v3.7) + SPAN-7 (v3.8, ADR 0034) ship a 3-source cross-correlator that pairs wire metadata, NGFW syslog, and NetFlow/IPFIX into per-flow verdicts. That answers "did the DUT log what it observed?" with eight verdicts including the smoking-gun dut_silent.

But customer interviews reveal five questions our pipeline still cannot answer:

  1. Long-flow correlation — a NetFlow active-timer emits records every 60s through an 8h SSH session; today's NetFlowWindow=5min declares miss_flow before the flow actually ends. False positives at scale.
  2. Deny rule effectiveness — the DUT writes action=deny to syslog AND the flow transfers 50MB. Today this is misclassified, which is ambiguous between "deny killed mid-handshake (~2KB)" and "deny was silently bypassed (50MB transferred)". Auditors need the distinction.
  3. Decryption coverage — what percentage of TLS flows is the DUT actually decrypting? Customer paid for "100% TLS inspection" but a bypass rule, a wildcard exception, or a configuration error may have created a hole the DUT itself doesn't surface.
  4. Decryption engine health — fail-open silencioso, buffer overflow under load, certificate engine failures, NPU offload errors — all of which make the DUT say it's inspecting while inspecting nothing. Spirent and Keysight measure decryption performance under load; they don't measure decryption coverage.
  5. Fast-path / flow offload — the most expensive blind spot. Many NGFW vendors (Fortinet, Check Point, Sophos, Cisco FTD with Flow Offload, Juniper Express Path) ship features that decrypt+inspect only the initial N packets of a flow, then hand the rest to hardware fast-path that bypasses deep inspection. Customers paid $500K-2M for full inspection and get inspection of the first ~5% of bytes per session, with the DUT's own logs reporting "everything was inspected".

These are all manifestations of one umbrella property: DUT inspection effectiveness — does the DUT actually do what it claims to do, throughout the flow lifetime, for the volume of traffic it processes? This ADR captures the design for validating that property across six pillars.

Decision

Adopt a six-pillar approach to DUT inspection effectiveness validation:

# Pillar Wave Effort Patent claim
1 Flow lifecycle correlator SPAN-7c ~8 h extends #16
2 deny_ineffective verdict SPAN-7b+ ~1 h extends #16
3 Decryption posture indicators SPAN-8 (5 PRs) ~24 h new family (Decryption Posture)
4 Cert-based decryption detection SPAN-8a ~10 h new family (Decryption Posture)
5 Fast-path / flow offload detection SPAN-9 (5 PRs) ~35 h new family (Fast-Path Detection)
6 Inspection Effectiveness Score SPAN-9d ~6 h extends Fast-Path family

Total: ~84 h spread across ~10-15 sessions. Pillars 1+2 close out the SPAN-7 wave; pillars 3+4 open the SPAN-8 wave; pillars 5+6 open the SPAN-9 wave.


Pillar 1 — Flow lifecycle correlator (SPAN-7c)

Problem statement

NetFlow/syslog events arrive at different points in a flow's lifetime:

Signal Start Mid End
Wire (SPAN) ✅ ClientHello (encrypted payload, opaque) TCP FIN/RST
Syslog Cisco FTD/ASA %ASA-6-302013 Built TCP %ASA-6-302014 Teardown
NetFlow active-timer flow-start record records every 60s flow-end (inactive-timer +15s)
NetFlow inactive-only only at end

A 30-min file upload produces a built record at t=0, 30 active-timer NetFlow records at t∈[60s, 1800s], and a teardown record at t=1800s. SPAN-7's NetFlowWindow=5min collapses this into 6 distinct partial verdicts instead of one full-lifecycle verdict.

Solution

Replace the snapshot-style pendingFlow with a lifecycle state machine:

type FlowLifecycle struct {
    Key       string

    // Wire side — typically one handshake per session, but
    // session resumption / renegotiation may add more.
    Handshakes []types.MetadataEvent

    // Syslog — explicit start/end events from %ASA / equivalents.
    BuiltAt    *time.Time
    BuiltRec   *types.SyslogRecord
    TornDownAt *time.Time
    TornDownRec *types.SyslogRecord

    // NetFlow — multiple records expected over the flow lifetime.
    NetFlows []types.NetFlowRecord

    // State machine
    State        FlowState
    OpenedAt     time.Time   // engine-clock first signal arrival
    LastSignalAt time.Time   // for stale detection
}

type FlowState string
const (
    FlowStateActive            FlowState = "active"            // gathering signals, flow alive
    FlowStateAwaitingClose     FlowState = "awaiting_close"    // teardown detected, waiting for final NetFlow
    FlowStateClosedCorrelated  FlowState = "closed"            // verdict emitted, flow GC'd
    FlowStateClosedPartial     FlowState = "closed_partial"    // expired with missing signals
)

Verdict timing

Two verdict classes:

  • Interim verdict — emitted while flow active; carries interim: true field. Operator sees real-time signal but understands it can be revised.
  • Final verdict — emitted when flow definitively closes. Authoritative; enters Annex.

A flow is considered closed when any of:

  1. Syslog teardown record observed
  2. NetFlow record with flow_end populated AND flow_end < now - safety_margin
  3. No signal for the flow in > max_silence_window (default 10 min)
  4. Wire FIN/RST observed (requires SPAN-2 to emit a FlowCloseEvent — new event type, scope SPAN-7c)

Schema impact

ValidationReport gains:

type ValidationReport struct {
    // ... existing fields ...

    // SPAN-7c additions
    LifecyclePhase     LifecyclePhase    `json:"lifecycle_phase,omitempty"`     // active | closed | closed_partial
    Interim            bool              `json:"interim,omitempty"`              // true if revisable
    FlowDuration       time.Duration     `json:"flow_duration_ns,omitempty"`     // BuiltAt → TornDownAt
    SignalEventCount   int               `json:"signal_event_count,omitempty"`   // total signals seen for this flow
}

Backward compatibility

Configurable via --lifecycle-mode=(snapshot|stateful). Default snapshot for v3.7/v3.8 zero-diff upgrade; operators opt in to stateful when they need long-flow accuracy.


Pillar 2 — deny_ineffective verdict (SPAN-7b+)

Problem statement

Today's misclassified verdict fires when DUT logs deny but wire shows TLS ClientHello. This is ambiguous:

  • (a) DUT denied a flow but logged after seeing the handshake (technically correct, late log) — ~1-2 KB transferred
  • (b) DUT logged deny but the flow completed successfully — 50 MB transferred — compliance failure

Auditors need (a) and (b) distinguished. They sound the same in the Annex today.

Solution

New verdict deny_ineffective, sub-class of misclassified, fires when:

syslog.action ∈ {deny, drop, block}
AND wire shows ClientHello (TLS metadata present)
AND evidence of substantial transfer:
    EITHER NetFlow available with bytes_total > 5_000
    OR wire shows N≥3 application-data packets after ClientHello (SPAN-9a will give us per-packet evidence)

The 5 KB threshold is calibrated to "completed handshake + first application-data packet" — anything below is "deny killed mid-handshake" (still misclassified, less severe).

Rule entry

Added to pkg/span-correlator/internal/correlator/internal_check.go as rule #5:

{
    name:  "deny_ineffective",
    check: ruleDenyIneffective,
}

func ruleDenyIneffective(s *types.SyslogRecord, m *types.MetadataEvent, n *types.NetFlowRecord) (bool, string) {
    if !isDeny(s) || !isTLS(m) { return false, "" }
    bytesEvidence := uint64(0)
    if n != nil { bytesEvidence = n.BytesTotal() }
    if bytesEvidence < 5_000 { return false, "" }
    return true, fmt.Sprintf(
        "DUT logged action=%q but NetFlow confirms %d bytes transferred — deny rule INEFFECTIVE",
        s.Action, bytesEvidence)
}

Verdict applies in modes that include both wire AND NetFlow (i.e. wire_netflow, fusion_3way). In wire_syslog mode without NetFlow input, falls back to misclassified.

Annex impact

New section in dut-annex when count > 0:

⚠️ Compliance failures detected

The DUT logged deny/drop/block for the following flows, but NetFlow evidence confirms substantial data transfer completed: | Rank | Flow | Bytes transferred | Vendor | Action logged |

This is a stand-alone compliance reporting surface — sells separately to compliance/audit roles.


Pillar 3 — Decryption posture indicators (SPAN-8)

Problem statement

Customer paid for "100% TLS inspection" but cannot answer:

  • What % of TLS flows is actually being decrypted?
  • Which SNIs / IPs / applications are bypassing decryption?
  • Did decryption coverage drop today vs yesterday (fail-open detection)?
  • Did decryption coverage drop under load (engine saturation)?
  • Are there specific cert/cipher patterns the DUT consistently can't decrypt (engine bug)?

Spirent/Keysight measure decryption performance under contrived load. They don't measure decryption coverage in production-like conditions. Whitespace.

Solution

New module pkg/decryption-posture that consumes MetadataEvent records (enriched with cert info by Pillar 4) and emits four classes of indicator:

3a. Coverage gauge

type CoverageSample struct {
    SampledAt          time.Time `json:"sampled_at"`
    WindowSeconds      int       `json:"window_seconds"`
    TotalTLSFlows      int       `json:"total_tls_flows"`
    DecryptedFlows     int       `json:"decrypted_flows"`
    BypassedFlows      int       `json:"bypassed_flows"`
    UnknownFlows       int       `json:"unknown_flows"` // cert info missing
    CoveragePercentage float64   `json:"coverage_percentage"`
}

Sampled per N-second window (default 60s). Time-series exposed via Prometheus + Dashboard.

3b. Bypass list

Live ranking of SNIs / Destination IPs / inferred-applications that are bypassing decryption.

type BypassEntry struct {
    Identifier     string       // SNI or DstIP or app-id-style label
    IdentifierType string       // "sni" | "dst_ip" | "application"
    BypassCount    int
    LastSeen       time.Time
    Reason         BypassReason // explicit_policy | unknown_ca | tls13_ech | unsupported_cipher | tampering_detected | other
}

Top-N (default 50). Dashboard surface lets operator click "Add to decryption policy" — exports a vendor-specific config snippet (Cisco FTD ACL, PAN decryption policy rule, FGT SSL inspection profile entry) that the operator pastes into their DUT to fix the gap.

3c. Fail-open detection (anomaly)

Statistical baseline of coverage_percentage over a learning window (default 7 days). Alert when:

  • Coverage drops > 2σ below baseline for > 5 min
  • Coverage drops abruptly (>10 pp in <60 s)
  • Bypass-list churn rate spikes (new SNIs entering bypass-list at unusual rate)

Each is an independent Prometheus alert rule plus a Dashboard "fail-open" banner.

3d. Engine-health correlated indicators

When SNMP / IPMI / vendor-API metrics are available (via existing module integrations), correlate:

  • Coverage drop ↔ DUT CPU > 90 % → likely buffer overflow / engine saturation
  • Coverage drop ↔ DUT memory > 90 % → likely cert-cache eviction
  • Coverage drop ↔ specific cipher patterns (e.g. all TLS 1.3 ECDHE-X25519 bypass) → likely engine-side support gap

These correlations are emitted as HealthCorrelationEvent records — annexed to the report and surfaced on Dashboard.


Pillar 4 — Cert-based decryption detection (SPAN-8a)

Problem statement

How do we know whether a TLS flow was decrypted? Certificate issuer evidence.

Scenario Cert in ServerHello (from client's POV)
Bypass (DUT does not decrypt) Server's real CA (DigiCert, Let's Encrypt, ...)
MITM (DUT decrypts) DUT's CA (NGFW corporate root, manually distributed as trusted)

Today SPAN-2 (span-tls-extractor) parses ClientHello only. It does not extract ServerHello cert info. We need to.

Solution

Extend pkg/span-tls-extractor to parse:

  1. ServerHello — negotiated cipher_suite, negotiated TLS version, session_id, NewSessionTicket detection
  2. Certificate handshake message — first cert in chain (server's leaf):
  3. Subject CN + SAN list
  4. Issuer CN + O
  5. SHA-256 fingerprint
  6. NotBefore + NotAfter
  7. Public key algorithm

Schema additions to TLSHandshakeMetadata:

type TLSHandshakeMetadata struct {
    // ... existing v3.7 fields ...

    // SPAN-8a additions
    NegotiatedCipherSuite   string    `json:"negotiated_cipher_suite,omitempty"`
    NegotiatedTLSVersion    string    `json:"negotiated_tls_version,omitempty"`

    CertSubjectCN           string    `json:"cert_subject_cn,omitempty"`
    CertSubjectSAN          []string  `json:"cert_subject_san,omitempty"`
    CertIssuerCN            string    `json:"cert_issuer_cn,omitempty"`
    CertIssuerO             string    `json:"cert_issuer_o,omitempty"`
    CertFingerprintSHA256   string    `json:"cert_fingerprint_sha256,omitempty"`
    CertNotBefore           time.Time `json:"cert_not_before,omitempty"`
    CertNotAfter            time.Time `json:"cert_not_after,omitempty"`
    CertPublicKeyAlgorithm  string    `json:"cert_public_key_algorithm,omitempty"`
}

Decryption classification

Operator configures the DUT CA fingerprint registry in the Dashboard:

dut_ca_fingerprints:
  - vendor: cisco-ftd
    fingerprint_sha256: "ab12..."
    description: "Lab NGFW corporate CA"
  - vendor: cisco-ftd
    fingerprint_sha256: "cd34..."
    description: "Production NGFW intermediate CA"

pkg/decryption-posture classifies each MetadataEvent cert:

Cert fingerprint matches Classification
Known DUT CA decrypted
Known public CA (Mozilla CA bundle) bypassed
Neither unknown (logged for operator review — could be self-signed, internal CA, attack)

Dual-tap support (SPAN-8d follow-up)

Single-tap (internal segment, client↔DUT) is sufficient for the decryption classification above — we see DUT cert vs Server cert directly in the ServerHello.

Dual-tap (client↔DUT AND DUT↔server) adds: - Differential view — confirm the DUT is actually negotiating different sessions on both sides - Latency analysis (foundation for Pillar 5)

Dual-tap is optional for Pillars 3+4; required for Pillar 5's latency-based fast-path detection.


Pillar 5 — Fast-path / flow offload detection (SPAN-9)

Problem statement (the crown jewel)

Many NGFW vendors implement "fast-path" features that:

  • Decrypt + deep-inspect the first N packets / first KB of a TLS flow
  • Classify the flow (app-id, threat-category, policy decision)
  • Hand the rest of the flow to hardware fast-path (NPU/ASIC/FPGA) which forwards without deep inspection

The DUT's own logs report "TLS classification: app-X" and the customer believes 100 % of bytes were inspected. In reality, only the first ~5 % was. Malicious payloads positioned later in the flow pass through invisibly.

Vendor implementations (status as of 2026-Q2):

Vendor Feature Default? Variant
Cisco FTD/ASA Flow Offload (Snort to hardware) OFF (but common in prod) A
Fortinet FortiGate NP/SP offload (FortiASIC) ON A
Check Point SecureXL + Templates ON A
Palo Alto App-ID early classification ON (with continued inspection) weak A
Juniper SRX Express Path / Services Offload OFF A
Sophos XG FastPath ON A→B hybrid
Forcepoint NGFW Flow inspection optimization ON B (rare)

Two variants:

  • Variant A — "decryption MITM, inspection offload": DUT keeps the MITM keys throughout the session (cert evidence still shows DUT CA), but the deep inspection engine (Snort, App-ID, IPS) is disabled for that flow after threshold N. Most common.
  • Variant B — "full bypass after handshake": DUT decrypts + inspects the handshake, then abandons MITM. From packet N+1 onwards the flow is end-to-end client↔server (cert switches from DUT to Server). Less common but exists.

Solution: three detection strategies, used in combination

5a. Cert evolution detection (passive, catches variant B only)

Within the same FiveTuple key, observe ServerHello cert sequence:

Handshake #1 (t=0):     ServerHello cert = DUT CA  → MITM active
Handshake #2 (t > 0):   ServerHello cert = Server CA → MITM abandoned

The second handshake could be a TLS renegotiation, session resumption, or session reset. Either way, the cert-issuer transition from DUT-CA to Server-CA is the signal.

Effort: small (~3 h) once Pillar 4's cert parsing is in place.

5b. Differential latency histogram (passive, catches variants A + B; needs dual-tap)

Most robust strategy. Requires SPAN taps before AND after the DUT with sub-millisecond timestamping (PTP-synchronized or kernel-bypass capture).

For each flow, compute per-packet latency through the DUT: latency_pkt_k = T_external_k − T_internal_k. Plot the per-flow latency distribution.

Inspection mode Latency distribution shape
Full deep inspection throughout unimodal, high mean (e.g. 200-800 µs)
Fast-path active from packet N bimodal: first N pkts at high latency, packets N+1+ at low latency (e.g. 20 µs)

Bimodality detection via Gaussian Mixture Model (2 components) fit on the per-flow histogram. Threshold N is the inflection point (the "knee" between the two Gaussians). The ratio of low-latency to high-latency means is the fast-path acceleration factor.

Emit FastPathDetected event per flow:

type FastPathDetected struct {
    Tuple                   types.FiveTuple
    DetectedAt              time.Time
    ThresholdPacketIndex    int           // first packet of low-latency mode
    HighLatencyMeanNs       int64         // typical deep-inspection latency
    LowLatencyMeanNs        int64         // typical fast-path latency
    AccelerationFactor      float64       // high/low
    Confidence              float64       // GMM goodness-of-fit score
}

Effort: high (~12 h). Requires dual-tap infrastructure.

5c. Active canary injection (active, catches variants A + B; most conclusive)

Test-time strategy. During a controlled test, the Playwright/k6 agent runs a "canary playbook":

canary_playbook:
  session: tls-1.3
  destination: target-persona
  packets:
    - offset: 0
      payload: benign_pattern_seed
    - offset: 1..10
      payload: random_benign
    - offset: 50
      payload: eicar_signature_over_tls       # canary #1
    - offset: 200
      payload: snort_test_rule_pattern        # canary #2
    - offset: 1000
      payload: known_ips_signature            # canary #3
    - offset: 5000
      payload: known_ips_signature            # canary #4

For each canary, observe whether the DUT generates an alert/log/block. The first canary that fails to trigger is the inferred fast-path threshold.

Report:

Fast-path threshold detected: between packets 200 and 1000
DUT inspected canaries at offsets: 0, 50, 200
DUT failed to inspect canaries at offsets: 1000, 5000
Confidence: HIGH (3 of 4 expected detections present)

Effort: medium (~8 h). Reuses existing Playwright/k6 agent infra + SPAN-3's syslog correlation.

5d. Statistical baseline (heuristic, low confidence)

Track DUT alert rate per byte transferred across many flows in production. Flows where alert rate drops sharply mid-session (relative to early-flow baseline) suggest fast-path engagement. Weak signal individually; useful in aggregate as a Grafana panel against the FLOW.Art TSDB.

Effort: low in code (~2 h SPAN-3 instrumentation); medium in dashboarding (~6 h Grafana).

Strategy combination

Strategy Variant A Variant B Active? Effort
Cert evolution passive small
Latency histogram passive (dual-tap) high
Canary injection active medium
Statistical baseline weak weak passive low

Ship the first three as a coherent wave (SPAN-9a, SPAN-9b, SPAN-9c). Strategy 5d is deferred to a Grafana follow-up.


Pillar 6 — Inspection Effectiveness Score (SPAN-9d)

Single aggregate metric for operator + executive consumption: an Inspection Effectiveness Score (IES) in [0, 100]:

IES = decryption_coverage_pct
    × (1 − fast_path_bypass_ratio)
    × deny_effectiveness_factor
    × lifecycle_completeness_factor
Factor Source Range
decryption_coverage_pct Pillar 3 — gauged % of TLS flows decrypted [0, 1]
fast_path_bypass_ratio Pillar 5 — bytes after threshold / total bytes (averaged across flows where fast-path detected) [0, 1]
deny_effectiveness_factor Pillar 2 — 1 − (deny_ineffective_count / total_deny_logged) [0, 1]
lifecycle_completeness_factor Pillar 1 — 1 − (closed_partial_count / total_flows) [0, 1]

Surfaced as: - A primary Dashboard gauge (huge, color-coded green/yellow/red) - The lead KPI in the Annex header - The headline number in the executive summary report - A Prometheus gauge tlsstress_dut_inspection_effectiveness_score

Headline pitch (sample marketing)

"Customer X's Fortinet 7060F: claimed 100 % TLS inspection. Measured IES: 34 %. Diagnosis: - 89 % decryption coverage (11 % of TLS flows bypassed — see policy gaps below) - 71 % fast-path bypass ratio (NPU offload aggressive — average flow inspected only on first 1.2 KB out of 12 MB) - 8 % of deny-logged flows transferred > 5 KB of data - 4 % of flows closed without complete telemetry correlation"

That paragraph closes deals. The whole stack exists to be able to print it.


Architecture overview

Module / responsibility map after all six pillars ship:

pkg/span-collector            (existing, v3.7 — libpcap T1 ingress)
  ↓ PacketBatch
pkg/span-tls-extractor        (existing v3.7 + SPAN-8a extension: ServerHello + Cert parsing)
  ↓ MetadataEvent (enriched)
pkg/span-correlator           (existing v3.7 + v3.8 + SPAN-7b deny_ineffective + SPAN-7c lifecycle)
  ↓ ValidationReport (interim + final)
  ├→ pkg/dut-annex            (Annex renderer, mode-aware)
  ├→ pkg/decryption-posture   (NEW — Pillar 3, coverage + bypass-list + fail-open)
  └→ pkg/flow-art             (NEW NetFlow sink + downstream TSDB)
        ↑ NetFlow records (Pillar 1 lifecycle aware)

pkg/dut-latency-analyzer      (NEW — Pillar 5b, dual-tap latency histogram)
  ↓ FastPathDetected events

pkg/canary-injector           (NEW — Pillar 5c, test-time playbook engine)
  ↓ canary detection results

pkg/inspection-effectiveness  (NEW — Pillar 6, IES aggregator + Dashboard tile)

Module boundaries deliberately respected

  • span-correlator stays focused on cross-correlation. It does not classify decryption posture or detect fast-path — those are downstream consumers.
  • decryption-posture is a stand-alone module so customers without SPAN-2/SPAN-3 (perhaps using third-party flow collectors) can still consume just this pillar if they pipe MetadataEvent-shaped JSON in.
  • dut-latency-analyzer is dual-tap-only; gracefully degrades to "unsupported" when only one tap is configured.
  • canary-injector is test-time only; not deployed in production correlator path.

Rollout

Recommended sequence balancing patent priority, commercial demonstration value, and engineering risk:

Order Wave Purpose Effort
1 SPAN-7b (planned) + Pillar 2 deny_ineffective Close SPAN-7 wave + ship one new compliance verdict (small win) 5 + 1 h
2 SPAN-7c (Pillar 1 lifecycle) Stops false positives in long flows — prerequisite for production 8 h
3 SPAN-7a (Dashboard SourceSelector — planned) UX for v3.8 features 4 h
4 SPAN-8a (Pillar 4 cert parsing) Foundation for Pillars 3 + 5a 10 h
5 SPAN-9c (Pillar 5c canary injection) Most commercially demonstrable smoking gun; binary result 8 h
6 SPAN-9e provisional patent draft (Fast-Path + Canary) Lock priority date 4 h
7 SPAN-8b-d (Pillar 3 — coverage + bypass-list + fail-open) Decryption posture indicators 14 h
8 SPAN-8e provisional patent draft (Decryption Posture) Lock priority date 4 h
9 SPAN-9a + 9b (Pillar 5a cert evolution + 5b latency analyzer) Complete the fast-path detection trio 15 h
10 SPAN-9d (Pillar 6 IES aggregator + Dashboard tile) Crown jewel UX 6 h

Total: ~79 h spread across ~12-15 sessions.

Critical path: SPAN-7c is the prerequisite for clean production behavior. Without it, every long flow in production yields false positives. Ship that before any v3.9 release.

Patent strategy: file provisional for Fast-Path family before Pillar 5b ships publicly (priority date matters). Same for Decryption Posture family before Pillar 3.

Consequences

Pros

  • Six pillars together convert SPAN.Art from "DUT log validator" to "NGFW Effectiveness Validator" — a 5-10× pricier product category
  • Three distinct patent families (extends #16 + Decryption Posture + Fast-Path Detection) — defensible IP moat
  • Each pillar is independently shippable and demonstrable
  • Pillar 5c (canary injection) produces binary, instantly-explainable results — perfect for proof-of-value engagements
  • Pillar 6 IES gives the headline number that closes deals
  • Pillar 2 (deny_ineffective) creates a stand-alone compliance reporting surface — sells to audit/compliance roles separately

Cons / risks

  • Total wave is large (~79 h) — risk of mid-stream pivot if customer signal contradicts assumptions; mitigate by shipping smallest-most-demonstrable first (Pillar 2 + Pillar 5c)
  • Pillar 5b (latency histogram) requires dual-tap infrastructure customers may not have — clearly mark as "requires dual-tap" and offer Pillar 5c (canary) as the always-available alternative
  • Pillar 4 (cert parsing) opens cryptographic-protocol-parsing attack surface — must use stdlib parsers, no third-party deps, fuzz tests required
  • Patent FTO scans are non-trivial — IDS/IPS evasion and middlebox-inspection are dense patent spaces. Budget for legal review.
  • Pillar 5c (canary injection) using EICAR or Snort test signatures in production is forbidden — must be opt-in test-time only, with operator confirmation in Dashboard

Compatibility

  • All pillars are additive — no v3.7 / v3.8 deployments regress
  • New ValidationReport fields are optional (omitempty)
  • Pillar 1's stateful lifecycle mode is opt-in (default snapshot)
  • Pillar 3 is a separate module (no impact on existing pipeline)
  • Pillar 5 is dual-tap-aware (single-tap deployments simply skip 5b)

Patent angle

Existing #16 family (extends)

ADR 0035 sharpens claim #16:

  • Per-flow lifecycle correlation with asymmetric per-signal timing windows (Pillar 1)
  • deny_ineffective verdict via NetFlow-volume + syslog-action differential (Pillar 2)
  • Bidirectional inspection effectiveness validation under operator-configurable source set (Pillars 3-6 reinforce 0034's adaptive-multi-source element)

Proposed new family: Decryption Posture Validation

Independent claim: A method for validating TLS decryption coverage of a network middlebox via passive observation of certificate-issuer evidence in ServerHello messages, comprising: - Registry of trusted decryption-device CA fingerprints - Per-flow classification (decrypted / bypassed / unknown) by matching observed cert against registry - Aggregation into time-series coverage metrics - Anomaly detection for fail-open events via baseline deviation - Correlation of coverage with device health telemetry

Differentiation from prior art: - Spirent/Keysight measure decryption performance (PPS/throughput) — not coverage - Vendor-supplied tools (Cisco Secure Workload, PAN Cortex) report intent — not measured evidence - Academic prior art (CCS, NDSS) focuses on attack-side TLS-MITM detection — adversarial framing, different scope

Proposed new family: Fast-Path Detection in TLS-Inspecting Middleboxes

Independent claim: A method for detecting hardware-accelerated bypass of deep-inspection in TLS-inspecting middleboxes, comprising: - Dual-tap packet capture with sub-millisecond timestamping before and after the middlebox - Per-flow latency histogram construction - Bimodality detection via Gaussian Mixture Model fit - Threshold-packet identification from inter-mode inflection point - Acceleration-factor calculation from mode latency ratio

Dependent claim: further comprising mid-session injection of detection-canary payloads with known IDS/IPS signatures at controlled packet offsets, observation of middlebox alert/log generation per canary, and correlation of canary detection failures with passive latency-based bimodality signals.

Differentiation from prior art: - "Fast-path" is documented terminology among NGFW vendors (lay-of-the-land) - Combination of (latency analysis + canary injection) is non-obvious - Existing IDS evasion research focuses on attacker-side techniques to bypass IDS; this is the inverse — defender-side technique to discover that the IDS is bypassing itself - Existing middlebox correctness checkers (LinkSmith, Mochi, etc.) focus on protocol compliance, not inspection effectiveness

FTO scan required for both new families before drafting: - Espacenet + USPTO + Google Patents search on: "TLS inspection coverage", "middlebox decryption verification", "deep inspection bypass detection", "network device fast-path detection" - Estimated 4-6 h legal/IP work for scan + claim drafting - Run in parallel with engineering work; results don't block code but inform claim scope

Open questions for future ADRs

  1. CA fingerprint registry distribution — manually managed today; should DUT auto-discovery probe DUT API to retrieve cert? (defer to v4.x)
  2. Canary signature library — start with EICAR-over-TLS + Snort test rules + ETPro samples; eventually need a curated signature library with weekly updates (paid feed or own curation?)
  3. Dual-tap infrastructure recommendations — what NIC + driver + clock-sync stack do we recommend customers deploy for Pillar 5b? Mellanox ConnectX-6 + PTP4L + DPDK-style timestamping is the gold standard; document this in docs/SPAN_DUAL_TAP_GUIDE.md (separate doc PR)
  4. Privacy implications of cert observation — observing customer TLS metadata may have GDPR/LGPD implications even when decrypted content stays inside the network. Review with legal before shipping Pillar 4 publicly.
  5. Performance under high coverage compute — Pillar 5b's GMM fitting per flow at 10 Gbps could saturate CPU. Plan a load test before claiming production-ready.

References

  • ADR 0024 — SPAN.Art line-rate capture (parent of pillar 1)
  • ADR 0034 — SPAN.Art 3-way fusion correlator (parent of pillars 1-2)
  • Patent claim #16 family (extends)
  • RFC 5246, RFC 8446 — TLS 1.2 / 1.3 (foundation for Pillar 4 cert parsing)
  • RFC 7011 — IPFIX (foundation for Pillar 1 NetFlow timing model)
  • Cisco FTD documentation: "Flow Offload" (vendor literature for Pillar 5 detection target)
  • Fortinet NSE 7 / NP/SP offload literature
  • Check Point SecureXL administration guide
  • Snort 3 IPS rule reference (Pillar 5c canary library seeds)
  • Mozilla CA bundle (Pillar 4 reference public CA list)
  • NIST SP 800-52r2 — TLS server config baselines
  • Memory companion: discuss_dut_inspection_effectiveness_2026_05_13.md