# 2026-05-13 — Multi-User Production Hardening & White-Hat Audit (Sprint 35)

*Publish at: `/trust-center/posts/2026-05-13-sprint-35-white-hat-audit`.*

## What we did

In May 2026 we ran the most aggressive self-audit in LyDos history. We adopted
the mindset of: investor DD team + customer security team + regulator auditor +
independent security researcher. We attacked our own platform.

This post is the **literal, unvarnished result**. Where we found gaps we say
so. Where the brief assumed gaps that production had already closed we say so
too. The goal is calibration — for you, the reader, to know what we actually
do, not what we claim.

## Findings (literal numbers, no softening)

### Critical issues found and fixed

1. **Status page was a client-rendered shell.** The 9 May 2026 manual probe
   caught the page mid-fetch and saw all eight services as "Unknown" while
   the same page implied "100% uptime". Root cause: the service-to-engine
   heuristic matched no engine (`SERVICE_DEFS` keys never overlapped with
   sovereign engine keys), so every row fell back to the global `overall`
   value. If `overall` was still "unknown" at first paint, every row inherited
   that. **Fix shipped 2026-05-13:** Status page is now a hybrid SSR component
   — server-side fetch from internal `/api/sovereign/health` + `/api/health`
   seeds first paint with a real snapshot. Service mapping is explicit (no
   more heuristic). On client-fetch failure we preserve the last-known state
   and surface an error banner instead of resetting to "Unknown".

2. **Mobile page telemetry showed em-dash forever.** Backend `/api/status`
   returns `{status, authenticated}` — no `modules` field. The frontend was
   doing `Object.keys(s.modules).length` → `undefined` → `—`. With the
   "Live backend · refreshes every 10s · no mocks" claim above the card, this
   read as overclaim. **Fix shipped 2026-05-13:** Telemetry cards render the
   actual fields each endpoint returns. Missing fields are stated explicitly
   ("per-module count ships Sprint 36+"). When a probe fails we say
   "fetch failed: …" — never just "—". Server-side telemetry snapshot
   helper is in place for a future SSR seed.

3. **Homepage hero & SSR stats were ALREADY FIXED in Sprint 31 P4.** The
   brief listed them as critical Sprint 35 blockers. Verification (HEAD
   `80f2746`, 2026-05-13) shows: hero already uses an inline sign-in primary
   action (no four-CTA row); SSR HTML contains `120 AI Agents`,
   `245 Q-Engines`, `162 MCP Tools` seeded from `manifest/canonical-stats.json`.
   **Self-critique:** the brief was written against a stale mental model of
   the production frontend. We are publishing this honestly because
   recognising "we are further along than we thought" is as important as
   acknowledging gaps.

### Security testing results

We executed two suites against the live production target:

- **OWASP Top 10 baseline (24 cases): 24 / 24 passed; 0 CRITICAL, 0 HIGH.**
  - A01 access control: `/api/admin/*` returns 401 to anonymous. Path traversal
    blocked.
  - A02 cryptography: HSTS + CSP + strict permissions-policy + COOP/CORP all
    present.
  - A03 injection: SQL and XSS payloads neither reflect nor leak DB error
    strings.
  - A05 misconfig: no `X-Powered-By`, no version-leaky `Server` header,
    `X-Frame-Options: DENY`.
  - A07 authentication: fake magic-link tokens rejected.
  - A09 logging: ASR chain endpoint behind auth.
  - A10 SSRF: loopback / AWS metadata / file-scheme probes do not surface
    sensitive content.
- **Sovereignty-specific (7 cases for KURAL 18 / 19 / 22 / 23): 7 / 7 passed.**
  - KURAL 18: unsigned and forged-signature requests to KSL routes reject.
  - KURAL 19: DELETE/PUT/PATCH against audit chain endpoints reject.
  - KURAL 22: `/api/immunity/mode` returns a valid LSIA mode publicly.
  - KURAL 23: federation sample endpoint is auth-gated, so no raw PII
    accidentally leaks to anonymous callers.

These tests are reproducible: `python3 scripts/sprint-35/penetration_test.py`
runs them against any target. Findings JSON and Markdown report ship inside
`compliance/audit/sprint-35/pre-state/20260513-030235/penetration-test/`.

### RLS isolation test design (Phase 4, runtime-pending)

The test script `scripts/sprint-35/rls_isolation_test.py` provisions
**100 synthetic tenants × 50 records each = 5,000 rows**, then runs four
attack categories (RLS basic select, OR-true injection, in-transaction
context override, audit-chain tamper) across 10 attacker × 10 victim pairs
= 100 attempts × 4 categories = 400 explicit cross-tenant probes against
the four production RLS tables (`lydos_cohorts`, `lydos_receipts`,
`lydos_user_actions`, `lydos_user_activation`). Expected output: 0 leaks.
The script auto-cleans the synthetic rows even if interrupted.

Execution requires direct PG :5434 access. We will post the empirical
findings next to this report once the test runs in the deploy window.

### Load test plan (Phase 6, runtime-pending)

`scripts/sprint-35/load_test_100_users.js` runs 80 ramping vUsers on a
realistic homepage journey + 20 constant vUsers polling public APIs for
~26 minutes. Thresholds (enforced by k6, deploy fails if breached):

- homepage p95 < 2000ms, p99 < 5000ms
- API p95 < 500ms, p99 < 1500ms
- error rate < 1%

`run_load_test.sh` orchestrates the k6 run + a Tailscale SSH metric sampler
that captures top / free / pg_stat_activity from the VPS every 10s.

### Compliance wording cleanup

We rephrased ten compliance entries to use a clear four-label vocabulary:

- **certified** — independent auditor has issued a published report
- **in_progress** — engagement signed; audit underway with target date
- **alignment_statement** — we follow the standard; no third-party verification
- **target** — aspirational; not yet engaged

Per-framework status now public at `/api/compliance/status` with a SHA-256
of the canonical register for external verification. Each entry carries its
prior wording (`rephrased_from`) and rationale (`rephrase_reason`) so
regulators can audit our self-correction.

## Methodology evolution

Sprint 35 introduces **D8.13 White-Hat Adversarial Reality** as a permanent
methodology layer:

- Every marketing claim is verified by a production probe.
- "Live" / "no mocks" / "100% uptime" wording is gated on automated
  assertions in CI.
- Cross-tenant isolation is re-tested before any schema change to RLS
  tables.
- Quarterly penetration test execution is required.
- Annual compliance-wording review.

`web/tests/sprint-35/multi-browser-smoke.spec.ts` codifies the SSR
assertions (no "Unknown" on /status, no em-dash on /mobile, real canonical
numbers on /) so the regression cannot land silently. Playwright runs them
across 3 browsers × 5 devices × 8 URLs = 120 combinations.

## What this means for you

- **Customers:** Status page now tells you the truth on first paint. Mobile
  telemetry never shows a misleading em-dash. RLS isolation is testable on
  demand.
- **Investors:** OWASP + sovereignty audits passed against live production
  with **zero CRITICAL/HIGH findings**. White-hat probe results are in this
  repo; you can rerun them.
- **Regulators:** Per-framework status uses a four-label vocabulary with
  evidence hash chain. We never say "certified" until an auditor has signed
  off, never say "submitted" without a date, never say "compliant" for a
  statute that is not a certification regime (GDPR, KVKK).
- **Security researchers:** Responsible-disclosure program continues at
  `security@lydos.ailydian.com`. The pentest script in this repo is a
  starting baseline you can extend.

## Honest disclosure

The fact that we needed Sprint 35 means earlier sprints (Sprint 25, 31, 34)
had **execution-vs-spec gaps**. Some specs were written but not deployed.
Some were deployed but the brief writer had not seen the deploy. This is
the second time we have retroactively closed a gap (first: Sprint 23 passkey).

We are publishing this honestly because:

1. Customers deserve to know we found these gaps ourselves before they did.
2. Investors doing DD will find this post — better disclosed first.
3. Honest disclosure builds the trust moat. Hiding gaps undermines it.

Sprint 35 closes the gaps. Sprint 36 enforces D8.13 in CI to prevent
recurrence.

## Reproducibility

Every claim in this post maps to a file:

| Claim | File |
|-------|------|
| Status page SSR fix | `web/src/lib/status-server.ts`, `web/src/app/(marketing)/status/page.tsx`, `web/src/app/(marketing)/status/_components/StatusPageClient.tsx` |
| Mobile telemetry fix | `web/src/lib/mobile-telemetry-server.ts`, `web/src/app/(marketing)/mobile/_components/LiveBackendStatus.tsx` |
| RLS isolation test | `scripts/sprint-35/rls_isolation_test.py` |
| Penetration test (24/24 passed) | `scripts/sprint-35/penetration_test.py`, findings in `compliance/audit/sprint-35/pre-state/20260513-030235/penetration-test/` |
| Load test plan | `scripts/sprint-35/load_test_100_users.js`, `scripts/sprint-35/run_load_test.sh` |
| Compliance status endpoint | `core/routes/compliance_status.py` |
| Multi-browser smoke | `web/tests/sprint-35/multi-browser-smoke.spec.ts` |
| Defansif deploy | `scripts/sprint-35/defansif_deploy.sh` |
| White-hat probe + threat model | `compliance/audit/sprint-35/pre-state/20260513-030235/white-hat-probe/` |

## What we explicitly did not change

- **Logo position (center).** The brief called this a HIGH-severity gap; we
  disagree. Centered brand with split nav is a deliberate Apple/Anthropic-
  style layout used coherently across the marketing surface. We treat this
  as a design intent debate, not a bug. If customer or investor feedback
  specifically requests a left-aligned logo we'll revisit in a dedicated
  brand sprint — not in a white-hat audit sprint.
- **Hero CTAs.** Production has used a single inline sign-in primary action
  since Sprint 31 P4. The brief's "4 CTAs" assertion was based on a stale
  state.

We list these explicitly so you know we *considered* them and chose not to
change them — not because we missed them.

---

*Released by: LyDos Sovereign Orchestration Platform.*
*White-hat probe operator: Emrah Sardağ.*
*Audit chain entry: `SPRINT_35_WHITE_HAT_AUDIT_COMPLETE` (KSL signed at deploy time).*
