Data-Handling Statement

Published 2026-09-24 (v1; v1.1 same day; v1.2 2026-10-12) · Every claim dated and verified at rows · Versioned & dated

Verification status: every retention window below was read from the live deletion job's source and cross-checked against the oldest row in each governed table on 2026-09-24 (§11). Gaps are disclosed in §8 and stay listed until cured. Companion page: ZDR Provider Scorecard — same honesty standard, provider posture and our posture reported separately, never blended.

0. Honesty rules (this statement's contract with the reader)

  1. Every claim is verified against the running system, not policy aspiration. Retention windows below are not intentions — they were read from the live deletion job's source and cross-checked against the oldest row in each governed table on 2026-09-24 (§7).
  2. UNKNOWN is a first-class verdict. Where we don't know (e.g., telemetry of self-hosted reference stacks), we say so (§8).
  3. We verify and disclose; we do not control upstream. Providers can change terms at any time; the scorecard tracks that. This statement describes our own lane.
  4. Disclosed gaps stay listed until cured. We do not quietly fix and forget (§8); cures land as dated change-history entries.
  5. Vendor self-attestation is labeled as such and never presented as independent verification.
  6. This statement is versioned. The version you read is the version in force; prior versions remain available on request.

---

1. Scope

This statement covers: the design-r.ai website, its chat widget, the newsletter/waitlist, and the Design-R gateway — the AI-routing layer behind our own instances and (as services launch) client workloads. It describes what we collect, where it flows, how long it is kept, who can see it, and what we never do.

---

2. What we collect and retain

DataCollectedWhere it livesNotes
Newsletter subscriptionemail address, frequency choice (daily/weekly/monthly), optional per-service waitlist selections, opt-in stateself-hosted Postgres (app.newsletter_subscribers)double opt-in (48h confirmation token, stored as hash); one-click unsubscribe deletes the subscription row (code path verified 2026-09-24)
Website chat widgetyour messages, an optional display name, the page URL you messaged from, a session identifierself-hosted Postgres (app.widget_messages)display name is optional; IP addresses are not stored with messages (rate limiting is in-memory, not persisted) — see §8 G2 for one legacy exception
Operational logsinvocation metadata, tool-call logs, request/response envelopes for our AI instancesself-hosted Postgresneeded to run and debug the gateway; retention §7
Analyticspage views, referrers, search termsself-hosted Umami (first-party)no third-party analytics, no ad networks, no cross-site tracking
Emailwhat you send usself-hosted mail stack (Stalwart)business lane hello@design-r.ai; city-ops lane info@design-r.ai

We do not collect payment data (subscriptions disabled at launch; no checkout rails). We do not run advertising or tracking pixels.

---

3. What we forward (sub-processors)

Client-visible prompt content leaves our infrastructure only to the AI providers our instances route through. Live lanes, roster-verified 2026-09-24 (provider registry census, base URLs row-true):

Sub-processorEndpointRole
Ollama Cloudollama.commodel inference (primary lanes)
Fireworks AIapi.fireworks.aimodel inference (ZDR-default for open models — scorecard §2.1)
OpenCodeopencode.ai (zen endpoint)model inference
Self-hosted open-weight servingour own hardware (LAN)model inference — no third-party egress

Everything else stays on our infrastructure: database, email (self-hosted Stalwart), analytics (self-hosted Umami), file storage. No third-party email-service providers, no third-party analytics, no advertising networks, no data brokers. (Bridge topology independently row-verified 2026-09-24 by the gateway author: no analytics SDK, no third-party calls in the client path.)

Per-provider data-handling verdicts (retention, training, human review, jurisdiction) live in the ZDR Provider Scorecard §2 — provider posture and our posture are always reported separately, never blended.

---

4. What we never do

  • We do not train models on client data — contractual and operational (scorecard §3, L2: PASS). This claim is about our infrastructure: what providers do with forwarded content is governed by their own terms and tracked in scorecard §2 — it is not ours to row-verify, and we do not claim it for them.
  • No sale of data, no ad-tech, no data-broker transfers.
  • No third-party processors beyond §3.
  • No hidden human review — see §5.
  • No quiet policy changes — see §10.

---

5. Human review

The operator and authorized city instances can inspect transcripts, widget messages, and operational logs for operations, support, and debugging. This is disclosed, not hidden (scorecard §3, L3: PARTIAL — the same verdict we apply to ourselves as we apply to providers).

---

6. Credentials and redaction

  • Provider API keys live in a credential-wall secret store, referenced (not stored in plaintext) by the gateway's provider registry; secrets resolve at request time.
  • A credential-redaction layer (credential-guard v9) sits at the database-write choke point, layer specifics verified by its author (second-seat, 2026-09-24 20:35Z): (1) name-based — credential-shaped column names (token / secret / password / api_key / credential / auth_key / access_key / private_key / ws_token); (2) field-layer — expression-result fields redacted when the query text references credential-shaped substrings or credential-bearing tables; (3) value-layer — object/array-shaped cells not in sanctioned hash forms (md5/sha1/sha256/sha512 hex) are redacted, alias-agnostic and expression-covering. Redactions are values-blind ({__redacted, len, sha16} projections preserved so audits stay possible without exposure) and lane-uniform: one embedded guard file enforces identically across all gateway query lanes.
  • Observed live during this statement's audit (2026-09-24 ~20:34Z): census legs touching secret-bearing columns were automatically redacted by guard v9 at the accessor lane.
  • Known limits, disclosed (author-verified): the guard is a node-accessor guard — direct raw-SQL lanes (psql) do not ride it; scalar values in non-credential-named columns can evade the name layer (scalar name-evasion residual); sanctioned hash forms deliberately stay green (hashes are not secret material). These are coverage limits we track, not secrets we keep.

---

7. Retention schedule (configured vs. observed)

Retention job: runs every 6 hours (30-minute check interval), wired into gateway start/stop. Source: scheduler/retention.js; verified live 2026-09-24 20:32–20:35Z by comparing each table's oldest row against its configured window.

DataConfiguredOldest row observed 2026-09-24Status
Request/response envelopes (api_responses)30 days + 24h safety buffer2026-08-25 18:22Z✅ enforcing (boundary)
Invocation metadata (audit.invocations)90 days2026-06-27 00:09Z✅ enforcing (boundary)
Tool-call logs (audit.tool_log)90 days2026-07-26 13:28Z✅ within window (table younger than window; boundary expected ~Oct 24)
DB-write audit (audit.db_write_audit)90 days2026-06-26 18:04Z✅ enforcing (boundary)
Usage ledger (audit.usage_ledger)90 days2026-06-27 00:09Z✅ enforcing (boundary)
Embedding cache (memory.embedding_cache_768)90 days2026-06-27 00:10Z✅ enforcing (boundary)
Vector memories (memory.vector_memories)90 days2026-06-27 03:45Z✅ enforcing (boundary)
Outpost heartbeats (app.outpost_heartbeats)30 days2026-09-10 01:02Z✅ within window
Transcripts, facts, decisionspreserved—city memory; not auto-purged
Widget messages (app.widget_messages)none configured2026-07-13 20:36Z⚠️ gap — §8 G1

---

8. Known gaps (disclosed, with planned cures)

  • G1 — Widget message retention. 1,971 visitor/agent messages since 2026-07-13 with no retention job. Cure: add widget messages to the retention schedule (proposed 90 days) before any client widget onboarding. Status: cure queued.
  • G2 — Legacy widget-session table. One row (2026-07-13) holds a visitor IP + user agent; the current widget code no longer writes this table. Cure: purge the row; retire or drop the table. Status: cure queued.
  • G3 — Self-hosted reference-stack telemetry. UNKNOWN per scorecard §2.4 (vLLM anonymous usage stats documented; opt-out env vars listed there). Applies to our serving stack, not client content.
  • G4 — Daily re-verification automation. CURED 2026-10-12: policy-watch v0 (task #1713) is live — manual baseline run 00:45:36Z UTC (12/12 URLs clean), then first unattended fire 06:45:59Z UTC verified green (12/12 clean, 0 changes, 0 fails; public status feed: latest-status.json). Like the scorecard, this statement does not yet claim "checked daily" — that claim follows a proven daily cadence. The go-live disclosure both pages promised has landed as dated entries this day (§10 v1.2 here; scorecard header, same day).

---

9. Your rights (UK GDPR)

  • Contact: hello@design-r.ai.
  • Access / erasure: email us; newsletter data is deleted on unsubscribe (row delete, verified code path); widget content is deletable on request.
  • Minimization: the newsletter stores email + preferences only; double opt-in; emails are sent from our own infrastructure with no tracking pixels.
  • No profiling: the chat widget is an assistant surface, not a profiling system; no automated decision-making about you.

---

10. Changes

VersionDateChange
v12026-09-24Initial publication. Retention windows verified at rows (§7); sub-processor list from live provider-registry census (§3); redaction state per §6 with live-fire observation; gaps disclosed §8.
v1.12026-09-24Author second-seat (Bathys, 20:35:36Z) folded same hour: precise redaction layering + lane-uniformity + precise limits (§6); "no training" claim scoped to our infrastructure, provider-side pointed to scorecard §2 (§4); bridge no-third-party-calls verification noted (§3).
v1.22026-10-12Gap G4 cured: policy-watch v0 live — manual baseline 00:45:36Z + first unattended fire 06:45:59Z verified green (12/12 clean, 0 changes, 0 fails; public feed live). §8 G4 updated to CURED with dated receipt; "checked daily" claim still withheld pending proven daily cadence.

Corrections policy: published errors are corrected loudly with a dated entry here. When the retention schedule, sub-processor list, or redaction layer changes, this statement is re-verified and re-versioned within one cycle of the change.

---

11. How this was verified

All-SELECT audit at rows, 2026-09-24 20:30–20:36Z (Poros, accessor lane, audit-logged, zero mutation): retention liveness (oldest-row vs configured window per table), provider-registry census (enabled lanes + base URLs, values-blind), widget-storage census (counts, timestamps, schema columns), credential-guard live-fire observation. Second-seat verification of the redaction-state legs landed from the redaction layer's author (Bathys) 2026-09-24 20:35:36Z — layer specifics, lane-uniformity, and limits folded same hour; his independent row-verification of the bridge topology (no third-party calls in the client path) is cited in §3.

Source files read for this statement: scheduler/retention.js, lib/pg-accessor.js (credential-guard v9), routes/widget.js, engine/llm-router-native.js (provider loading), plus the live database census above.

Try it now — chat with one of our AI team members. This is the kind of intelligence we build for client businesses.