Skip to content

ADR-0084: HAR.Art — L7 HAR replay (10k sessions/host)

  • Status: Accepted (2026-05-24) — full HAR wave (HAR-1..HAR-4) materialized; client engine + dashboard + K8s deploy + this ADR all shipped to main in PRs #1031 / #1032 / #1033 / this PR
  • Date: 2026-05-24
  • Driver: discuss_har_art_2026_05_10 locked HAR.Art as the missing L7 replay primitive between PW.Art (browser, ~50 sessions/host) and DoYour.Art Replay (PCAP, packet-level). Memo identified five use cases unreachable from either side: WAF false-positive testing, cross-vendor regression, performance attribution, multi-region testing, load multiplication
  • Related: PRs #1031 (HAR-1), #1032 (HAR-2), #1033 (HAR-3), this PR (HAR-4); strategic memo discuss_har_art_2026_05_10; sister-MÓDULO ADRs ADR-0081 (DoYour.Art Phase A) + ADR-0082 (KALI.Art Phase A) + ADR-0036 (HyperBridge.Art inline tap)

Context

The TLSStress.Art TAM has three distinct audiences who need application-layer replay against an NGFW DUT:

  1. Web QA engineers — record a checkout flow in DevTools, replay it after a config change, prove the NGFW didn't break the user journey
  2. WAF admins — customer reports "your WAF blocks our real users on /api/checkout"; we need their HAR captured during the broken session and the ability to replay it against the customer's WAF config in our lab
  3. Performance engineers — "the checkout is 8s slow, is it the NGFW?" Replay with and without NGFW; the delta = NGFW contribution

PW.Art (Playwright fleet) ships a full browser at ~200–500 MB / session × ~50 sessions / host — too heavy for the load-multiplication use case ("1 HAR × 10000 = realistic flash-sale load"). DoYour.Art Replay tab handles PCAP at L2-L4 — the wrong layer entirely for L7 semantics (fresh TLS handshake, different source IPs, etc.). Neither covers the gap.

No commercial bench ships HAR replay first-class (Spirent BreakingPoint, Keysight CyberFlood, Ixia BreakingPoint — none have HAR; only open-source puppeteer-har / har-replay-server, with zero observability/UI/scale).

Decision

Ship MÓDULO HAR.Art as a 4-sub-PR wave (HAR-1..HAR-4):

Sub-PR Scope Status
HAR-1 New Go module pkg/har-art/ — W3C HAR 1.2 parser, header rewrite + PII anonymizer, concurrent replay engine, CLI/server binary, Prometheus metrics. 17 unit tests ✅ #1031
HAR-2 Drizzle 0038 har_art_replay_sessions + dual-mode store with tier caps + 5 API routes + admin page /admin/har-art + 29 i18n keys × 3 locales. 9 store tests ✅ #1032
HAR-3 K8s manifests namespace har-art + NAD VLAN 2903 slot .83 + gVisor + Deployment + 100 GiB RWX PVC har-library + Drizzle 0039 har_art_operator_libraries per-operator metadata + tier-bound quotas ✅ #1033
HAR-4 ADR-0084 (this PR) + module docs 3-lang expansion + recovery memo

Locked defaults — 5 open questions from the memo

The memo listed 5 open questions; this ADR locks each:

# Question Locked answer
1 HTTP client choice Custom Go net/http — pure stdlib, no CGO, no browser engine dependency. Trade-off: not browser-faithful (no JS execution, no DOM, no cookie-jar lifecycle). The memo's "WAF tuning + cross-vendor regression + perf attribution" use cases don't need browser fidelity; they need scale + identical L7 wire format. Browser fidelity stays in PW.Art
2 HAR storage Local PVC har-library (RWX, 100 GiB default) — ReadWriteMany so multiple har-replay-client replicas can read the same HAR concurrently (the load-multiplication use case). S3/MinIO defer to a Phase B follow-up if/when the on-prem deployments need offsite storage
3 Throughput target MVP 10 000 concurrent sessions/host per the memo's headline. One goroutine per session + shared HTTP/2 transport pool + atomic counters (no mutex contention) hit this comfortably on the 4-core / 4 GiB envelope from HAR-3's Deployment limits
4 Multi-browser HAR fidelity Vendor-extension-tolerant parser; semantic re-issue rather than byte-for-byte replay. Chrome / Firefox / Safari HARs all replay identically through HAR.Art because the parser ignores the per-vendor sidecar fields (_serverIPAddress, _priority, etc.). The replayed traffic carries our synthetic User-Agent (operator-overridable), not the browser's
5 PII anonymization Auto-strip ON by default, opt-out via Policy.AnonymizePII=false. Curated 10-header strip list (Cookie, Set-Cookie, Authorization, Proxy-Authorization, X-Api-Key, X-Auth-Token, X-Csrf-Token, X-Session-Id, X-Forwarded-User, X-Real-Ip) + email / CC / SSN regex redaction in request bodies. Operators handling segregated lab traffic can disable; the safe default keeps customer HARs publishable to the dashboard's audit trail

Tier policy (locked)

Per the memo's "Free tier liberado — low-risk, web traffic":

Tier Concurrent runs Replay clients Duration cap HAR library
free 1 100 5 min 100 MiB · 5 files
indie 1 500 30 min 1 GiB · 25 files
team 3 5 000 2 h 10 GiB · 100 files
enterprise 10 10 000 24 h 100 GiB · unlimited

Tier caps return HTTP 429 with code: tier-* discriminator so the dashboard can render a coherent upsell path.

Architectural decision — standalone admin page

The dashboard page lives at /admin/har-art, NOT as an Art Studio tab. The memo is explicit: HAR.Art's audience (QA / WAF admins / app owners / perf engineers) is distinct from Art Studio's developer audience. Mixing them in tabs would dilute both surfaces.

Patent posture

Patent claim #17 (per the memo's "patent #17" reference, originally registered in the project-wide claims list). The novelty lever is the combination of: - W3C HAR replay at 10k-sessions/host scale - Auto-anonymizing PII at the replay layer (no commercial bench does this — every existing tool requires the operator to pre-scrub) - Tier-gated operator workflow with free-tier accessibility (no competitor offers free HAR replay)

FTO scan plan deferred to Phase B (when the cross-vendor regression use case generates the first customer demo). The puppeteer-har / har-replay-server open-source landscape has zero patent claims; commercial space (Spirent/Keysight/Ixia) doesn't ship HAR replay at all.

Consequences

Positive

  • The 4-sub-PR cadence kept each merge small + reviewable + revertable
  • Server-only / client-safe type separation (HAR-2 types.ts vs session-store.ts) keeps the Node crypto import out of the browser bundle while letting the admin page render tier-cap labels
  • PVC RWX choice enables horizontal scale-out for the load-multiplication use case without operator action
  • The 5-question lock removes ambiguity for the next operator who picks up HAR.Art work

Negative / deferred

  • Browser-faithful replaypuppeteer-har / Playwright HAR mode could replay JS-heavy SPAs with full DOM lifecycle. Decision: stays in PW.Art; HAR.Art remains semantic-replay-only
  • S3 / MinIO HAR storage — Phase B once the on-prem RWX PVC pattern hits scale limits
  • Browser fingerprint preservation — the synthetic User-Agent replaces the original; some WAFs do header-order / TLS-fingerprint inspection that we'd need to mimic. Deferred to a Phase B "fingerprint preservation" subdir
  • Dashboard HAR upload UI — HAR-2's admin page accepts a har_path pointing at the PVC, but the actual upload happens out-of-band (kubectl cp or operator-supplied via volume mount). A first-class drag-and-drop upload form is a Phase B follow-up
  • Quota CronJob — HAR-3 declares the har_art_operator_libraries schema but the nightly du -sb scan that updates bytes_used lands in a Phase B kali-quota-scan-style CronJob

Alternatives considered

  • Embed HAR replay in PW.Art — rejected; would couple the heavy browser fleet to the lightweight L7 use cases and dilute both audiences
  • Use Playwright's HAR mode — rejected for the engine; Playwright + headless Chromium is ~200–500 MB / session, defeating the 10k-sessions/host goal. Kept as a future option for browser-faithful replay in Phase B
  • Single Art Studio tab — rejected per the memo's audience-separation argument
  • RWO PVC + StatefulSet — rejected; load-multiplication requires multiple replicas reading the same HAR. RWX is the right model
  • Mandatory PII anonymization (no opt-out) — rejected; lab-only operators need to test against real auth tokens. Default-on with opt-out is the right compromise

Compliance

Per CLAUDE.md: "Dashboard is the ONLY operator interface." HAR-2 ships the standalone admin page with start / cancel / live counters — operator never types kubectl against the har-art namespace.

Per ADR-0044 (OOBI Intrusion Detection): the har-replay-client HTTP server listens on :9092 cluster-internal only; ingress / NetworkPolicy scoping is the same shape as the kali-art-mcp sidecar.

Per the locked ZTP-prem posture: gosec W0 baseline preserved (no inline #nosec annotations were needed in the new pkg/har-art/ package — pure stdlib net/http, no system calls beyond os.Open on operator-supplied flag paths which are documented as such).

References

  • discuss_har_art_2026_05_10 — strategic memo
  • ADR-0081 (DoYour.Art Phase A), ADR-0082 (KALI.Art Phase A), ADR-0036 (HyperBridge.Art) — sibling MÓDULOs in the offensive-tooling family
  • PRs #1031 (HAR-1), #1032 (HAR-2), #1033 (HAR-3), this PR (HAR-4)
  • Patent claim #17