<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent sightings.</title>
    <link>https://vulnerability.circl.lu</link>
    <description>Contains only the most 10 recent sightings.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Thu, 28 May 2026 11:23:07 +0000</lastBuildDate>
    <item>
      <title>64edd906-2d62-4cfd-a968-47ab2614f559</title>
      <link>https://vulnerability.circl.lu/sighting/64edd906-2d62-4cfd-a968-47ab2614f559/export</link>
      <description>{"uuid": "64edd906-2d62-4cfd-a968-47ab2614f559", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-4142", "type": "seen", "source": "https://bsky.app/profile/atomicedge.bsky.social/post/3mkdrtpj3at2c", "content": "", "creation_timestamp": "2026-04-25T19:33:06.599251Z"}</description>
      <content:encoded>{"uuid": "64edd906-2d62-4cfd-a968-47ab2614f559", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-4142", "type": "seen", "source": "https://bsky.app/profile/atomicedge.bsky.social/post/3mkdrtpj3at2c", "content": "", "creation_timestamp": "2026-04-25T19:33:06.599251Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/64edd906-2d62-4cfd-a968-47ab2614f559/export</guid>
      <pubDate>Sat, 25 Apr 2026 19:33:06 +0000</pubDate>
    </item>
    <item>
      <title>009fb0c7-b06f-4dea-8b64-02581b1ab95a</title>
      <link>https://vulnerability.circl.lu/sighting/009fb0c7-b06f-4dea-8b64-02581b1ab95a/export</link>
      <description>{"uuid": "009fb0c7-b06f-4dea-8b64-02581b1ab95a", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41428", "type": "seen", "source": "https://bsky.app/profile/cyberhub.blog/post/3mkl33hycs62p", "content": "", "creation_timestamp": "2026-04-28T17:07:08.821928Z"}</description>
      <content:encoded>{"uuid": "009fb0c7-b06f-4dea-8b64-02581b1ab95a", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41428", "type": "seen", "source": "https://bsky.app/profile/cyberhub.blog/post/3mkl33hycs62p", "content": "", "creation_timestamp": "2026-04-28T17:07:08.821928Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/009fb0c7-b06f-4dea-8b64-02581b1ab95a/export</guid>
      <pubDate>Tue, 28 Apr 2026 17:07:08 +0000</pubDate>
    </item>
    <item>
      <title>615224c4-9a96-4162-b5e7-9d89f1bad737</title>
      <link>https://vulnerability.circl.lu/sighting/615224c4-9a96-4162-b5e7-9d89f1bad737/export</link>
      <description>{"uuid": "615224c4-9a96-4162-b5e7-9d89f1bad737", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41429", "type": "seen", "source": "https://bsky.app/profile/cyberhub.blog/post/3ml5ta25iz32p", "content": "\ud83d\udccc CVE-2026-41429 - arduino-esp32 is an Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 microcontrollers. Prior to 3.3.8, there is a remot... https://www.cyberhub.blog/cves/CVE-2026-41429", "creation_timestamp": "2026-05-06T04:07:07.531958Z"}</description>
      <content:encoded>{"uuid": "615224c4-9a96-4162-b5e7-9d89f1bad737", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41429", "type": "seen", "source": "https://bsky.app/profile/cyberhub.blog/post/3ml5ta25iz32p", "content": "\ud83d\udccc CVE-2026-41429 - arduino-esp32 is an Arduino core for the ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 microcontrollers. Prior to 3.3.8, there is a remot... https://www.cyberhub.blog/cves/CVE-2026-41429", "creation_timestamp": "2026-05-06T04:07:07.531958Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/615224c4-9a96-4162-b5e7-9d89f1bad737/export</guid>
      <pubDate>Wed, 06 May 2026 04:07:07 +0000</pubDate>
    </item>
    <item>
      <title>5a45c3aa-5935-4b15-9dd1-ee0ba6129ff1</title>
      <link>https://vulnerability.circl.lu/sighting/5a45c3aa-5935-4b15-9dd1-ee0ba6129ff1/export</link>
      <description>{"uuid": "5a45c3aa-5935-4b15-9dd1-ee0ba6129ff1", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/thehackerwire.bsky.social/post/3mlbpgc6dvt2q", "content": "\ud83d\udfe0 CVE-2026-41422 - High (8.3)\n\nDaptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /aggregate/:typename endp...\n\nhttps://www.thehackerwire.com/vulnerability/CVE-2026-41422/\n\n#infosec #cybersecurity #CVE #vulnerability #security #patchstack", "creation_timestamp": "2026-05-07T17:09:42.242653Z"}</description>
      <content:encoded>{"uuid": "5a45c3aa-5935-4b15-9dd1-ee0ba6129ff1", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/thehackerwire.bsky.social/post/3mlbpgc6dvt2q", "content": "\ud83d\udfe0 CVE-2026-41422 - High (8.3)\n\nDaptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /aggregate/:typename endp...\n\nhttps://www.thehackerwire.com/vulnerability/CVE-2026-41422/\n\n#infosec #cybersecurity #CVE #vulnerability #security #patchstack", "creation_timestamp": "2026-05-07T17:09:42.242653Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/5a45c3aa-5935-4b15-9dd1-ee0ba6129ff1/export</guid>
      <pubDate>Thu, 07 May 2026 17:09:42 +0000</pubDate>
    </item>
    <item>
      <title>6b3612c1-9264-49a2-a2f2-f28b155ee27f</title>
      <link>https://vulnerability.circl.lu/sighting/6b3612c1-9264-49a2-a2f2-f28b155ee27f/export</link>
      <description>{"uuid": "6b3612c1-9264-49a2-a2f2-f28b155ee27f", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/2rZiKKbOU3nTafniR2qMMSE0gwZ.activitypub.awakari.com.ap.brid.gy/post/3mlbpidtvpoi2", "content": "\ud83d\udfe0 CVE-2026-41422 - High (8.3) Daptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /aggregate/:typename endp... https://www.thehackerwire.com/vulnerability/CVE-2026-41422/ #in...\n\n\nOrigin | Interest | Match", "creation_timestamp": "2026-05-07T17:11:55.730832Z"}</description>
      <content:encoded>{"uuid": "6b3612c1-9264-49a2-a2f2-f28b155ee27f", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/2rZiKKbOU3nTafniR2qMMSE0gwZ.activitypub.awakari.com.ap.brid.gy/post/3mlbpidtvpoi2", "content": "\ud83d\udfe0 CVE-2026-41422 - High (8.3) Daptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /aggregate/:typename endp... https://www.thehackerwire.com/vulnerability/CVE-2026-41422/ #in...\n\n\nOrigin | Interest | Match", "creation_timestamp": "2026-05-07T17:11:55.730832Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/6b3612c1-9264-49a2-a2f2-f28b155ee27f/export</guid>
      <pubDate>Thu, 07 May 2026 17:11:55 +0000</pubDate>
    </item>
    <item>
      <title>23590771-55a5-4d87-9efb-965d59ff319c</title>
      <link>https://vulnerability.circl.lu/sighting/23590771-55a5-4d87-9efb-965d59ff319c/export</link>
      <description>{"uuid": "23590771-55a5-4d87-9efb-965d59ff319c", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/thehackerwire.bsky.social/post/3mlbpvrgon72z", "content": "\ud83d\udfe0 CVE-2026-41422 - High (8.3)\n\nDaptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /aggregate/:typename endp...\n\nhttps://www.thehackerwire.com/vulnerability/CVE-2026-41422/\n\n#infosec #cybersecurity #CVE #vulnerability #security #patchstack", "creation_timestamp": "2026-05-07T17:18:20.572306Z"}</description>
      <content:encoded>{"uuid": "23590771-55a5-4d87-9efb-965d59ff319c", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/thehackerwire.bsky.social/post/3mlbpvrgon72z", "content": "\ud83d\udfe0 CVE-2026-41422 - High (8.3)\n\nDaptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /aggregate/:typename endp...\n\nhttps://www.thehackerwire.com/vulnerability/CVE-2026-41422/\n\n#infosec #cybersecurity #CVE #vulnerability #security #patchstack", "creation_timestamp": "2026-05-07T17:18:20.572306Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/23590771-55a5-4d87-9efb-965d59ff319c/export</guid>
      <pubDate>Thu, 07 May 2026 17:18:20 +0000</pubDate>
    </item>
    <item>
      <title>686e21b8-d652-4ef3-a447-708df8453e3e</title>
      <link>https://vulnerability.circl.lu/sighting/686e21b8-d652-4ef3-a447-708df8453e3e/export</link>
      <description>{"uuid": "686e21b8-d652-4ef3-a447-708df8453e3e", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/cve.skyfleet.blue/post/3mlbryeiah52e", "content": "CVE-2026-41422 - Daptin vulnerable to SQL injection via unvalidated goqu.L() calls in aggregate API\nCVE ID : CVE-2026-41422\n \n Published : May 7, 2026, 3:16 p.m. | 1\u00a0hour, 9\u00a0minutes ago\n \n Description : Daptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /a...", "creation_timestamp": "2026-05-07T17:55:34.555732Z"}</description>
      <content:encoded>{"uuid": "686e21b8-d652-4ef3-a447-708df8453e3e", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41422", "type": "seen", "source": "https://bsky.app/profile/cve.skyfleet.blue/post/3mlbryeiah52e", "content": "CVE-2026-41422 - Daptin vulnerable to SQL injection via unvalidated goqu.L() calls in aggregate API\nCVE ID : CVE-2026-41422\n \n Published : May 7, 2026, 3:16 p.m. | 1\u00a0hour, 9\u00a0minutes ago\n \n Description : Daptin is a GraphQL/JSON-API headless CMS. Prior to version 0.11.4, the /a...", "creation_timestamp": "2026-05-07T17:55:34.555732Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/686e21b8-d652-4ef3-a447-708df8453e3e/export</guid>
      <pubDate>Thu, 07 May 2026 17:55:34 +0000</pubDate>
    </item>
    <item>
      <title>87fd39c4-a1d1-4d6a-ac9c-163d776b4e19</title>
      <link>https://vulnerability.circl.lu/sighting/87fd39c4-a1d1-4d6a-ac9c-163d776b4e19/export</link>
      <description>{"uuid": "87fd39c4-a1d1-4d6a-ac9c-163d776b4e19", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41421", "type": "seen", "source": "https://bsky.app/profile/keiwork35.bsky.social/post/3mldle5irzt2m", "content": "\u3010\u8106\u5f31\u6027\u60c5\u5831\u3011 CVE-2026-41421 SiYuan\u306e\u8106\u5f31\u6027\u306b\u3064\u3044\u3066\n\nSiYuan desktop 3.6.5\u3088\u308a\u524d\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u306f\u3001\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u51e6\u7406\u306b\u8d77\u56e0\u3059\u308b\u8106\u5f31\u6027\u304c\u5b58\u5728\u3057\u307e\u3059\u3002POST /api/notification/pushMsg \u304c\u53d7\u3051\u4ed8\u3051\u308b user-controlled \u306a msg", "creation_timestamp": "2026-05-08T11:02:14.301542Z"}</description>
      <content:encoded>{"uuid": "87fd39c4-a1d1-4d6a-ac9c-163d776b4e19", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41421", "type": "seen", "source": "https://bsky.app/profile/keiwork35.bsky.social/post/3mldle5irzt2m", "content": "\u3010\u8106\u5f31\u6027\u60c5\u5831\u3011 CVE-2026-41421 SiYuan\u306e\u8106\u5f31\u6027\u306b\u3064\u3044\u3066\n\nSiYuan desktop 3.6.5\u3088\u308a\u524d\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u306f\u3001\u901a\u77e5\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u51e6\u7406\u306b\u8d77\u56e0\u3059\u308b\u8106\u5f31\u6027\u304c\u5b58\u5728\u3057\u307e\u3059\u3002POST /api/notification/pushMsg \u304c\u53d7\u3051\u4ed8\u3051\u308b user-controlled \u306a msg", "creation_timestamp": "2026-05-08T11:02:14.301542Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/87fd39c4-a1d1-4d6a-ac9c-163d776b4e19/export</guid>
      <pubDate>Fri, 08 May 2026 11:02:14 +0000</pubDate>
    </item>
    <item>
      <title>1533432e-fe0c-4d3e-83fb-5475ea4bc92d</title>
      <link>https://vulnerability.circl.lu/sighting/1533432e-fe0c-4d3e-83fb-5475ea4bc92d/export</link>
      <description>{"uuid": "1533432e-fe0c-4d3e-83fb-5475ea4bc92d", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41429", "type": "seen", "source": "https://bsky.app/profile/keiwork35.bsky.social/post/3mldle5h5if2b", "content": "\u3010\u8106\u5f31\u6027\u60c5\u5831\u3011 CVE-2026-41429 arduino-esp32\u306e\u8106\u5f31\u6027\u306b\u3064\u3044\u3066\n\narduino-esp32 3.3.8 \u3088\u308a\u524d\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u306f\u3001NBNS \u30d1\u30b1\u30c3\u30c8\u51e6\u7406\u7d4c\u8def\u306b\u30ea\u30e2\u30fc\u30c8\u304b\u3089\u5230\u9054\u53ef\u80fd\u306a\u30e1\u30e2\u30ea\u7834\u640d\u306e\u8106\u5f31\u6027\u304c\u3042\u308a\u307e\u3059\u3002", "creation_timestamp": "2026-05-08T11:02:15.711502Z"}</description>
      <content:encoded>{"uuid": "1533432e-fe0c-4d3e-83fb-5475ea4bc92d", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41429", "type": "seen", "source": "https://bsky.app/profile/keiwork35.bsky.social/post/3mldle5h5if2b", "content": "\u3010\u8106\u5f31\u6027\u60c5\u5831\u3011 CVE-2026-41429 arduino-esp32\u306e\u8106\u5f31\u6027\u306b\u3064\u3044\u3066\n\narduino-esp32 3.3.8 \u3088\u308a\u524d\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u306f\u3001NBNS \u30d1\u30b1\u30c3\u30c8\u51e6\u7406\u7d4c\u8def\u306b\u30ea\u30e2\u30fc\u30c8\u304b\u3089\u5230\u9054\u53ef\u80fd\u306a\u30e1\u30e2\u30ea\u7834\u640d\u306e\u8106\u5f31\u6027\u304c\u3042\u308a\u307e\u3059\u3002", "creation_timestamp": "2026-05-08T11:02:15.711502Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/1533432e-fe0c-4d3e-83fb-5475ea4bc92d/export</guid>
      <pubDate>Fri, 08 May 2026 11:02:15 +0000</pubDate>
    </item>
    <item>
      <title>600462e6-fbec-4a12-89bb-b9ffd50ec73c</title>
      <link>https://vulnerability.circl.lu/sighting/600462e6-fbec-4a12-89bb-b9ffd50ec73c/export</link>
      <description>{"uuid": "600462e6-fbec-4a12-89bb-b9ffd50ec73c", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41427", "type": "seen", "source": "https://gist.github.com/yanchuk/859e9c10826efe814725781953466c18", "content": "# Architecture \u2014 ai-survey-app\n\nA TanStack Start (React 19, SSR) app with an LLM at the center of the intake loop. Pilot Interview surface lives at `prototype-with-ai.ianchuk.com`; SaaS builder layer not yet shipped [user-stated].\n\n## Stack\n\n- Language: TypeScript 6 [user-stated].\n- App framework: TanStack Start with React 19, SSR [user-stated].\n- Chat UI: assistant-ui v0.12.26 + shadcn/ui [user-stated].\n- AI SDK: Vercel AI SDK v6, provider-neutral [user-stated].\n- AI provider (v1): Google Gemini 3 with thinking-mode routing [user-stated].\n- Database: PostgreSQL via Neon (serverless prod). Local dev: Docker `postgres:17-alpine` on port 5434 [user-stated].\n- ORM: Drizzle ORM [user-stated].\n- Validation: Zod (discriminated unions on the SDK boundary) [user-stated].\n- RPC: oRPC (type-safe OpenAPI) [user-stated].\n- Auth: Better Auth &amp;gt;=1.6.5 (CVE-2026-41427 fix pinned) [user-stated].\n- Analytics: PostHog \u2014 Web Analytics + Session Replay, server bootstrap via OpenTelemetry [user-stated; commits `631d8482`, `fc017ee1`, `65402fd7`].\n- Object storage: Cloudflare R2 production; MinIO in dev for S3 parity [user-stated].\n- Email: Resend (prod), Mailpit (dev) [user-stated].\n- Bot protection: Cloudflare Turnstile [user-stated].\n- Monorepo: Turborepo + pnpm [user-stated].\n- Build: Vite [user-stated].\n- Hosting: Railway Hobby with Nixpacks builder, auto-deploy on push to main. No Docker in production [user-stated].\n\n## AI subsystem\n\n- Orchestrator: `apps/web/src/features/pilot-interview/chat-handler.ts` [src: apps/web/src/features/pilot-interview/chat-handler.ts].\n- AI call: `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` [src: packages/ai/src/pilot-response.ts].\n- Vercel AI SDK pattern: `generateText(model, { output: Output.object({ schema, name: 'pilot_turn' }), system, messages, ... })` [user-stated].\n- Schema validation at the SDK boundary \u2014 Zod discriminated union via `InterviewUiToolSchema` over `ask_text | ask_single_select | ask_multi_select | ask_confirm | ask_voice | complete_interview` [user-stated].\n- 30-second timeout per attempt; one retry on undefined output or 5xx / 429 / timeout; never retried on 4xx (except 429) or unsupported-feature errors [user-stated].\n- Temperature 0.3 \u2014 deliberately below conversational defaults (~0.7) for structured reliability [user-stated].\n- System prompt re-rendered per turn with form goal, respondent context, and current extraction state via `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` [src: apps/web/src/features/pilot-interview/model-input-prompt-sections.ts].\n\n## Data flow\n\n1. When a respondent visits `prototype-with-ai.ianchuk.com`, a vanilla JS loader mounts the iframe and an anonymous session is created on the first message [user-stated].\n2. On the first turn the AI opening would render immediately, with no Start button and no progress bar (Epic 2.10) [user-stated].\n3. Each turn passes through `chat-handler.ts` to `generatePilotStructuredResponse()` [user-stated].\n4. The response is validated at the SDK boundary against the discriminated union; the handler then runs `.superRefine(extractionEmailRefinement)` for cross-field rules (email required if `contactConsent=true`) [user-stated].\n5. Transcript is persisted to `pilot_transcript_messages`; extraction state to `pilot_extractions`; session metadata to `pilot_interviews` [user-stated, per `apps/web/src/db/schema.ts`].\n6. A PostHog `pilot_chat_turn` event would fire per turn with `latencyMs`, `usage`, `confidence`; `pilot_interview_completed` would fire at the end with `completionScore`, `turns elapsed`, `language`, `confidence` [user-stated].\n\n## Persistence (Drizzle)\n\n- `pilot_interviews` \u2014 `sessionId`, `createdAt`, `status`, `respondentLanguage` [user-stated].\n- `pilot_transcript_messages` \u2014 `id` uuid, `sessionId` FK, `role`, `content` text, `createdAt` [user-stated].\n- `pilot_extractions` \u2014 `sessionId` FK PK, all extraction fields as jsonb/text, `completionScore` [user-stated].\n- Pooled Neon PgBouncer URL at runtime; direct URL only for migrations [user-stated].\n\n## Integrations\n\n- Email send via Resend (prod) and Mailpit (dev) [user-stated].\n- File storage via R2 with S3-compatible client; MinIO in dev for parity [user-stated].\n- Bot protection via Cloudflare Turnstile [user-stated].\n- Analytics via PostHog \u2014 Web Analytics, Session Replay, LLM Analytics on the chat path with env kill-switch and UA consent [user-stated; commit `65402fd7`].\n- PostHog server bootstrap via `@vercel/otel`-style OTel span processor \u2014 `chore(posthog): wire OTel + PostHogSpanProcessor server bootstrap` [user-stated; commit `fc017ee1`].\n\n## Deployment\n\n- Production: Railway Hobby + Nixpacks; `railway.json` declares `preDeployCommand: [\"pnpm -F web db:migrate\"]` [user-stated].\n- Healthcheck: `GET /` with 300s timeout, restart x 3 [user-stated].\n- Auto-deploy on push to `main` [user-stated].\n- Production URL: `prototype-with-ai.ianchuk.com`, Cloudflare-proxied [user-stated].\n- Secrets: `DATABASE_URL` (pooled), `DATABASE_URL_DIRECT` (migrations), `GOOGLE_GENAI_API_KEY`, `BETTER_AUTH_URL`, `POSTHOG_API_KEY`, `CF_R2_*` [user-stated].\n\n## Architectural discipline \u2014 provider neutrality\n\n- AI vendor SDKs are imported only in `@ai-survey/ai` [user-stated].\n- ESLint rule in `apps/web` blocks direct imports of vendor SDKs [user-stated].\n- Result: swap provider without touching app code.\n- Bake-off candidates listed but not yet installed: Anthropic, OpenAI, Fireworks, Groq [user-stated].\n\n## Tradeoffs I would call out\n\n- Vercel AI SDK v6 with `Output.object` trades raw model power for SDK-level validation. Cost: tied to whatever the SDK supports for structured output. Benefit: the discriminated union is enforced at one seam, not scattered across handlers.\n- Temperature 0.3 for structured reliability trades conversational warmth for parse-rate. The system prompt has to carry the warmth.\n- Retry only once, and only on transient failures. Cost: occasional user-visible failure. Benefit: no thundering-herd on a sticky 4xx; no quiet retry on a schema violation.\n- Railway Hobby + Nixpacks trades vendor portability for solo-dev speed. The escape hatch is that nothing in the AI layer is Railway-specific.\n- Pooled vs direct Neon URLs are split deliberately. Migrations bypass PgBouncer; runtime uses it. Cost: two env vars. Benefit: no surprise on prepared-statement edge cases.\n\n## Testing\n\n- Pre-push gate: `pnpm typecheck &amp;amp;&amp;amp; pnpm test &amp;amp;&amp;amp; pnpm test:e2e &amp;amp;&amp;amp; pnpm build` enforced by `.claude/rules/testing-gates.md` [user-stated].\n- Vitest unit + Playwright E2E both run before push; blocking pre-commit hook with no `--no-verify` escape [user-stated].\n- Test mode: `PILOT_TEST_MODE=1` on port 3210 with fixture-driven E2E [user-stated].\n- Test files observed: `apps/web/src/features/pilot-interview/__tests__/chat-handler.test.ts`, `packages/ai/src/__tests__/pilot-response.test.ts`, `packages/ai/src/__tests__/with-timeout.test.ts` [user-stated].\n- Baseline coverage: 0 unit + 0 E2E currently \u2014 project just scaffolded; first tests landing with feature 1 [user-stated].\n\n\n# Feature Evidence \u2014 ai-survey-app\n\n&amp;gt; Note: **actively hunting the paypal moment.** Original wedge (feedback-surface ICP across 11 surfaces) was tested and weakened by my own adversarial audit on 2026-05-14 (Codex + devil-advocate + user research). Current candidate wedge: **estate/probate solo-attorney intake** (confidence medium). 30-day validation in flight: 15 attorney discovery calls + 3 paid concierge pilots. The reversal is product discipline \u2014 pre-registered rubric, honest falsification, immediate re-aim \u2014 not a retreat. The features below describe what shipped technically; see `product-strategy.md` for the active wedge hunt.\n\n## Gaps\n\n- No external respondent data yet. PoC validated by founder + advisor only.\n- 0 unit tests + 0 E2E at baseline (TDD gate exists before tests land).\n- SaaS builder UI not shipped.\n- No paying customers, no pre-sales.\n\nConcrete shipped features. One-liner, location, proof. Ordered by what a recruiter for an AI Product Builder or Senior PM (AI) role would care about first.\n\n## AI features\n\n- **Conversational intake under structured-output discipline** \u2014 `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` wraps Vercel AI SDK v6 `generateText` with `Output.object({ schema, name: 'pilot_turn' })` [src: packages/ai/src/pilot-response.ts].\n- **Per-turn system-prompt regeneration with form goal + ICP + extraction state** \u2014 `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` rebuilds the prompt every turn so the model sees the running extraction [src: apps/web/src/features/pilot-interview/model-input-prompt-sections.ts].\n- **Discriminated-union schema at the SDK boundary** \u2014 `InterviewUiToolSchema` covers `ask_text | ask_single_select | ask_multi_select | ask_confirm | ask_voice | complete_interview` [src: apps/web/src/features/pilot-interview/schema.ts].\n- **Two-stage validation** \u2014 SDK boundary first, then `.superRefine(extractionEmailRefinement)` for cross-field rules [user-stated].\n- **Wire-input strictness** \u2014 `PilotInboundUserMessageSchema.strict()` rejects unknown keys; `id`, `role`, `createdAt` are server-assigned, never trusted from the wire [user-stated].\n- **30-second per-attempt timeout** \u2014 bounded by Vercel AI SDK call options; covered by `packages/ai/src/__tests__/with-timeout.test.ts` [user-stated].\n- **One-shot retry only on transient failures** \u2014 retries on undefined output, 5xx, 429, timeout; never on 4xx (except 429) or unsupported-feature errors [user-stated].\n- **Temperature 0.3 for structured reliability** \u2014 deliberately below conversational ~0.7 [user-stated].\n- **Gemini 3 thinking-mode routing** \u2014 provider config in `@ai-survey/ai`; vendor SDK imports walled off [user-stated].\n- **Provider isolation walled by ESLint** \u2014 vendor SDKs only importable inside `@ai-survey/ai`; only Gemini 3 wired today; no bake-off run yet [user-stated].\n\n## Conversational UX\n\n- **First-turn pre-warmth** \u2014 AI opening renders immediately on widget load; no Start button, no progress bar (Epic 2.10). Proof: `chat-handler.ts` first-turn path [src: apps/web/src/features/pilot-interview/chat-handler.ts].\n- **Anonymous session auto-created on first message** \u2014 no signup wall between the respondent and the dialog. Proof: session creation in handler [user-stated].\n- **Language pre-selected by URL param** \u2014 auto-detect planned but not shipped. Proof: language flow in `chat-handler.ts`; documented gap [user-stated].\n- **Mobile-fixed layout** \u2014 recent fixes addressing overflow. Proof: commits `d20fdce1`, `681f71f4` Fix pilot mobile layout overflow [user-stated].\n- **assistant-ui v0.12.26 + shadcn/ui chat surface** \u2014 Proof: dependency versions [user-stated].\n- **Voice intake variant** \u2014 `ask_voice` is one of the six UI tool variants in `InterviewUiToolSchema`. Voice preference adoption is on the metrics doc. Proof: schema variant name; metrics doc reference [user-stated].\n\n## Persistence\n\n- **`pilot_interviews` table** \u2014 `sessionId`, `createdAt`, `status`, `respondentLanguage` [src: apps/web/src/db/schema.ts].\n- **`pilot_transcript_messages` table** \u2014 `id` uuid, `sessionId` FK, `role`, `content` text, `createdAt` [src: apps/web/src/db/schema.ts].\n- **`pilot_extractions` table** \u2014 `sessionId` FK PK, extraction fields as jsonb / text, `completionScore` [src: apps/web/src/db/schema.ts].\n- **Neon PgBouncer vs direct URL split** \u2014 `DATABASE_URL` pooled at runtime, `DATABASE_URL_DIRECT` for migrations [user-stated].\n\n## Observability\n\n- **PostHog Web Analytics + Session Replay** \u2014 enabled; surveys and flags disabled [commit `631d8482`, user-stated].\n- **PostHog OTel + `PostHogSpanProcessor` server bootstrap** \u2014 [commit `fc017ee1`, user-stated].\n- **PostHog LLM Analytics on chat path** \u2014 env kill-switch and UA consent [commit `65402fd7`, user-stated].\n- **`pilot_chat_turn` event** \u2014 per turn: `latencyMs`, `usage`, `confidence` [user-stated].\n- **`pilot_interview_completed` event** \u2014 per session: `completionScore`, `turns elapsed`, `language`, `confidence` [user-stated].\n- **Awaited captureImmediate in flush** \u2014 a real reliability fix, not a docs change [commit `eb9c8fb7`, user-stated].\n\n## Tests and quality gates\n\n- **Pre-push gate** \u2014 `pnpm typecheck &amp;amp;&amp;amp; pnpm test &amp;amp;&amp;amp; pnpm test:e2e &amp;amp;&amp;amp; pnpm build`. Blocking pre-commit hook; `--no-verify` not allowed by rule. Proof: `.claude/rules/testing-gates.md` [user-stated].\n- **Vitest unit + Playwright E2E both run before push** \u2014 Proof: same gate file [user-stated].\n- **Test mode** \u2014 `PILOT_TEST_MODE=1` on port 3210, fixture-driven E2E. Proof: env flag in handler [user-stated].\n- **Observed test files** \u2014 `apps/web/src/features/pilot-interview/__tests__/chat-handler.test.ts`, `packages/ai/src/__tests__/pilot-response.test.ts`, `packages/ai/src/__tests__/with-timeout.test.ts`, `playwright.config.ts` plus `tests/e2e/` [user-stated].\n- **Baseline coverage: 0 + 0** \u2014 project just scaffolded; first tests landing with feature 1. Gate exists before the tests by design [user-stated].\n\n## Build harness\n\n- **`CLAUDE.md` as SSOT for all AI tools** \u2014 Proof: commit `db3aed35` docs(claude.md): rebuild as single SSOT for all AI tools [user-stated].\n- **Codex integration rules** \u2014 `.claude/rules/codex-integration.md` [user-stated].\n- **Codex findings ledger** \u2014 `docs/retro/codex-findings/YYYY-MM.md` with `caught_by: codex` provenance on every promoted finding. Feeds the `tasks-for-sonnet` trigger catalog via retro Step 3.5 [user-stated].\n\n## Deployment\n\n- **Railway Hobby + Nixpacks** \u2014 auto-deploy on push to `main` [user-stated, `railway.json`].\n- **`preDeployCommand: [\"pnpm -F web db:migrate\"]`** \u2014 migrations run before deploy [user-stated, `railway.json`].\n- **Healthcheck `GET /` with 300s timeout, restart x 3** [user-stated, `railway.json`].\n- **Auth pinned to Better Auth &amp;gt;=1.6.5** \u2014 picks up CVE-2026-41427 fix. Proof: dependency pin [user-stated; CVE id not independently verified].\n- **Cloudflare Turnstile bot protection** \u2014 on the public widget surface [user-stated].\n\n## Public proof\n\n- **Live URL** \u2014 `prototype-with-ai.ianchuk.com`, Ukrainian only, anonymous, public, Cloudflare-proxied [user-stated].\n- **Other gaps** \u2014 no published completion-rate numbers, no eval scoreboard, no customer logos, no compliance certifications [user-stated]. See Gaps section at top for the rest.\n\n\n# Source Index \u2014 ai-survey-app\n\nClaim ledger for the ai-survey-app evidence pack. Every fact in the other six files traces back here.\n\n## Source-backed claims\n\nMost claims in this pack are user-stated rather than file-cited because the source files were not opened in this evidence pass \u2014 the brief described them. Where a commit hash is given, it is a verbatim user-stated commit subject.\n\n- Stack identifiers (TypeScript 6, TanStack Start, React 19, assistant-ui v0.12.26, shadcn/ui, Vercel AI SDK v6, Gemini 3, PostgreSQL via Neon, Drizzle ORM, Zod, oRPC, Better Auth &amp;gt;=1.6.5, PostHog, Cloudflare R2, MinIO, Resend, Mailpit, Turborepo + pnpm, Vite, Railway Hobby + Nixpacks, Cloudflare Turnstile) [user-stated].\n- AI orchestrator path `apps/web/src/features/pilot-interview/chat-handler.ts` [src: apps/web/src/features/pilot-interview/chat-handler.ts].\n- AI call `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` [src: packages/ai/src/pilot-response.ts].\n- Vercel AI SDK call shape `generateText(model, { output: Output.object({ schema, name: 'pilot_turn' }), system, messages, ... })` [user-stated].\n- Schema discriminated union `InterviewUiToolSchema` over `ask_text | ask_single_select | ask_multi_select | ask_confirm | ask_voice | complete_interview` [user-stated].\n- Extraction schema `apps/web/src/features/pilot-interview/schema.ts:PilotExtractionBaseSchema` with the listed fields and `.trim().max(2000)` / `.max(500)` guards [src: apps/web/src/features/pilot-interview/schema.ts].\n- Two-stage validation: SDK boundary + handler `.superRefine(extractionEmailRefinement)` for `contactConsent =&amp;gt; email` [user-stated].\n- Wire input strictness `PilotInboundUserMessageSchema.strict()`; server-assigned `id` / `role` / `createdAt` [user-stated].\n- 30-second timeout per attempt; one retry on undefined / 5xx / 429 / timeout; never on 4xx (except 429) or unsupported-feature errors [user-stated].\n- Temperature 0.3 [user-stated].\n- System-prompt regenerator `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` with sections: opening context, turn instructions, conversation history, output contract, interview state [src: apps/web/src/features/pilot-interview/model-input-prompt-sections.ts].\n- Persistence tables `pilot_interviews`, `pilot_transcript_messages`, `pilot_extractions` in `apps/web/src/db/schema.ts` [src: apps/web/src/db/schema.ts].\n- Pooled vs direct Neon URLs at runtime vs migrations [user-stated].\n- PostHog events `pilot_chat_turn` (`latencyMs`, `usage`, `confidence`) and `pilot_interview_completed` (`completionScore`, `turns elapsed`, `language`, `confidence`) [user-stated].\n- Metrics doc `docs/product/pilot-learning-metrics.md` [user-stated].\n- Pre-push gate `pnpm typecheck &amp;amp;&amp;amp; pnpm test &amp;amp;&amp;amp; pnpm test:e2e &amp;amp;&amp;amp; pnpm build` per `.claude/rules/testing-gates.md`; blocking pre-commit hook with no `--no-verify` escape [user-stated].\n- Observed test files: `apps/web/src/features/pilot-interview/__tests__/chat-handler.test.ts`, `packages/ai/src/__tests__/pilot-response.test.ts`, `packages/ai/src/__tests__/with-timeout.test.ts`, `playwright.config.ts`, `tests/e2e/` [user-stated].\n- Baseline coverage: 0 unit + 0 E2E currently [user-stated].\n- Provider neutrality: vendor SDKs only in `@ai-survey/ai`; ESLint rule in `apps/web` enforces it [user-stated].\n- Bake-off candidates listed but not installed: Anthropic, OpenAI, Fireworks, Groq [user-stated].\n- Deploy: Railway Hobby + Nixpacks; `railway.json` `preDeployCommand: [\"pnpm -F web db:migrate\"]`; `GET /` healthcheck 300s, restart x 3; auto-deploy on `main` [user-stated].\n- Secrets: `DATABASE_URL` (pooled), `DATABASE_URL_DIRECT` (migrations), `GOOGLE_GENAI_API_KEY`, `BETTER_AUTH_URL`, `POSTHOG_API_KEY`, `CF_R2_*` [user-stated].\n- `CLAUDE.md` as single SSOT for all AI tools \u2014 `db3aed35` docs(claude.md): rebuild as single SSOT for all AI tools [user-stated].\n- `.claude/rules/codex-integration.md` Codex integration rules [user-stated].\n- Codex findings ledger `docs/retro/codex-findings/YYYY-MM.md` with `caught_by: codex` provenance, feeding `tasks-for-sonnet` trigger catalog via retro Step 3.5 [user-stated].\n- Live PoC URL `prototype-with-ai.ianchuk.com`, Ukrainian only, anonymous, public, Cloudflare-proxied [user-stated].\n- Recent commits (last 25): `cd78d2c8` Add pilot interview discovery docs; `a96dfa71` docs(agents) carry pilot lessons into saas guidance; `36dcca12` docs(retro) 2026-05-12 retrospective on pilot code lessons; `d20fdce1` and `681f71f4` mobile fixes / Fix pilot mobile layout overflow; `65402fd7` feat(posthog) wire LLM Analytics on chat path with env kill-switch + UA consent; `db3aed35` docs(claude.md) rebuild as single SSOT for all AI tools; `fc017ee1` chore(posthog) wire OTel + PostHogSpanProcessor server bootstrap; `631d8482` chore(posthog) enable Web Analytics + Session Replay; disable surveys + flags; `eb9c8fb7` fix(telemetry) await pending captureImmediate promises in flush() [user-stated].\n\n## User-stated / inferred claims\n\n- Oleksii Yanchuk is sole maintainer; the SaaS builder layer is not yet shipped; the GitHub repo is assumed public at `github.com/yanchuk/ai-survey-app` [user-stated].\n- The product is positioned as a conversational intake widget (shareable link + vanilla JS loader to iframe) [user-stated].\n- Product thesis reverted to draft on 2026-05-14 after the founder's Codex adversarial audit, devil-advocate pass, and user research [user-stated].\n- Current candidate wedge: estate / probate solo-attorney intake, confidence medium [user-stated].\n- Backup wedges held in reserve: septic / well / foundation contractor intake, solo therapist private practice intake [user-stated].\n- Next validation plan: 15 attorney discovery calls + 3 paid concierge pilots in 30 days [user-stated].\n- \"Busy people actually answer\" thesis is unproven outside founder and advisor anecdotes [user-stated].\n- Better Auth pin &amp;gt;=1.6.5 picks up CVE-2026-41427 fix [user-stated]. CVE id not independently verified in this pass.\n\n## Unsafe claims to avoid\n\n- Paying customer count or revenue \u2014 none.\n- Completion-rate numbers, response time, drop-off rate \u2014 not published.\n- Eval scores or accuracy numbers \u2014 no eval scoreboard exists.\n- Compliance posture (GDPR, SOC 2) \u2014 explicitly not certified per the brief.\n- \"First\", \"category-defining\", or \"the future of forms\" framing \u2014 unverifiable and the thesis was just reverted, so doubly inappropriate.\n- Calling the SaaS layer shipped \u2014 it is not.\n- Claiming production scale metrics \u2014 no quantitative production metrics exist beyond the founder PoC.\n\n## Strongest proof artifacts\n\n1. Live URL: `prototype-with-ai.ianchuk.com` \u2014 the only externally verifiable artifact.\n2. `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` \u2014 the structured-output call seam.\n3. `apps/web/src/features/pilot-interview/schema.ts` \u2014 the `InterviewUiToolSchema` discriminated union and `PilotExtractionBaseSchema` with field guards.\n4. `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` \u2014 the per-turn prompt regenerator.\n5. `apps/web/src/features/pilot-interview/chat-handler.ts` \u2014 the orchestrator, including `.superRefine(extractionEmailRefinement)`.\n6. `.claude/rules/testing-gates.md` \u2014 the pre-push TDD gate.\n7. Commit `db3aed35` \u2014 `CLAUDE.md` as SSOT for all AI tools.\n8. Commit `eb9c8fb7` \u2014 telemetry `flush()` reliability fix; a real bug caught and fixed, not a docs commit.\n9. `docs/retro/codex-findings/YYYY-MM.md` \u2014 the Codex audit ledger with provenance.\n", "creation_timestamp": "2026-05-16T16:32:11.000000Z"}</description>
      <content:encoded>{"uuid": "600462e6-fbec-4a12-89bb-b9ffd50ec73c", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-41427", "type": "seen", "source": "https://gist.github.com/yanchuk/859e9c10826efe814725781953466c18", "content": "# Architecture \u2014 ai-survey-app\n\nA TanStack Start (React 19, SSR) app with an LLM at the center of the intake loop. Pilot Interview surface lives at `prototype-with-ai.ianchuk.com`; SaaS builder layer not yet shipped [user-stated].\n\n## Stack\n\n- Language: TypeScript 6 [user-stated].\n- App framework: TanStack Start with React 19, SSR [user-stated].\n- Chat UI: assistant-ui v0.12.26 + shadcn/ui [user-stated].\n- AI SDK: Vercel AI SDK v6, provider-neutral [user-stated].\n- AI provider (v1): Google Gemini 3 with thinking-mode routing [user-stated].\n- Database: PostgreSQL via Neon (serverless prod). Local dev: Docker `postgres:17-alpine` on port 5434 [user-stated].\n- ORM: Drizzle ORM [user-stated].\n- Validation: Zod (discriminated unions on the SDK boundary) [user-stated].\n- RPC: oRPC (type-safe OpenAPI) [user-stated].\n- Auth: Better Auth &amp;gt;=1.6.5 (CVE-2026-41427 fix pinned) [user-stated].\n- Analytics: PostHog \u2014 Web Analytics + Session Replay, server bootstrap via OpenTelemetry [user-stated; commits `631d8482`, `fc017ee1`, `65402fd7`].\n- Object storage: Cloudflare R2 production; MinIO in dev for S3 parity [user-stated].\n- Email: Resend (prod), Mailpit (dev) [user-stated].\n- Bot protection: Cloudflare Turnstile [user-stated].\n- Monorepo: Turborepo + pnpm [user-stated].\n- Build: Vite [user-stated].\n- Hosting: Railway Hobby with Nixpacks builder, auto-deploy on push to main. No Docker in production [user-stated].\n\n## AI subsystem\n\n- Orchestrator: `apps/web/src/features/pilot-interview/chat-handler.ts` [src: apps/web/src/features/pilot-interview/chat-handler.ts].\n- AI call: `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` [src: packages/ai/src/pilot-response.ts].\n- Vercel AI SDK pattern: `generateText(model, { output: Output.object({ schema, name: 'pilot_turn' }), system, messages, ... })` [user-stated].\n- Schema validation at the SDK boundary \u2014 Zod discriminated union via `InterviewUiToolSchema` over `ask_text | ask_single_select | ask_multi_select | ask_confirm | ask_voice | complete_interview` [user-stated].\n- 30-second timeout per attempt; one retry on undefined output or 5xx / 429 / timeout; never retried on 4xx (except 429) or unsupported-feature errors [user-stated].\n- Temperature 0.3 \u2014 deliberately below conversational defaults (~0.7) for structured reliability [user-stated].\n- System prompt re-rendered per turn with form goal, respondent context, and current extraction state via `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` [src: apps/web/src/features/pilot-interview/model-input-prompt-sections.ts].\n\n## Data flow\n\n1. When a respondent visits `prototype-with-ai.ianchuk.com`, a vanilla JS loader mounts the iframe and an anonymous session is created on the first message [user-stated].\n2. On the first turn the AI opening would render immediately, with no Start button and no progress bar (Epic 2.10) [user-stated].\n3. Each turn passes through `chat-handler.ts` to `generatePilotStructuredResponse()` [user-stated].\n4. The response is validated at the SDK boundary against the discriminated union; the handler then runs `.superRefine(extractionEmailRefinement)` for cross-field rules (email required if `contactConsent=true`) [user-stated].\n5. Transcript is persisted to `pilot_transcript_messages`; extraction state to `pilot_extractions`; session metadata to `pilot_interviews` [user-stated, per `apps/web/src/db/schema.ts`].\n6. A PostHog `pilot_chat_turn` event would fire per turn with `latencyMs`, `usage`, `confidence`; `pilot_interview_completed` would fire at the end with `completionScore`, `turns elapsed`, `language`, `confidence` [user-stated].\n\n## Persistence (Drizzle)\n\n- `pilot_interviews` \u2014 `sessionId`, `createdAt`, `status`, `respondentLanguage` [user-stated].\n- `pilot_transcript_messages` \u2014 `id` uuid, `sessionId` FK, `role`, `content` text, `createdAt` [user-stated].\n- `pilot_extractions` \u2014 `sessionId` FK PK, all extraction fields as jsonb/text, `completionScore` [user-stated].\n- Pooled Neon PgBouncer URL at runtime; direct URL only for migrations [user-stated].\n\n## Integrations\n\n- Email send via Resend (prod) and Mailpit (dev) [user-stated].\n- File storage via R2 with S3-compatible client; MinIO in dev for parity [user-stated].\n- Bot protection via Cloudflare Turnstile [user-stated].\n- Analytics via PostHog \u2014 Web Analytics, Session Replay, LLM Analytics on the chat path with env kill-switch and UA consent [user-stated; commit `65402fd7`].\n- PostHog server bootstrap via `@vercel/otel`-style OTel span processor \u2014 `chore(posthog): wire OTel + PostHogSpanProcessor server bootstrap` [user-stated; commit `fc017ee1`].\n\n## Deployment\n\n- Production: Railway Hobby + Nixpacks; `railway.json` declares `preDeployCommand: [\"pnpm -F web db:migrate\"]` [user-stated].\n- Healthcheck: `GET /` with 300s timeout, restart x 3 [user-stated].\n- Auto-deploy on push to `main` [user-stated].\n- Production URL: `prototype-with-ai.ianchuk.com`, Cloudflare-proxied [user-stated].\n- Secrets: `DATABASE_URL` (pooled), `DATABASE_URL_DIRECT` (migrations), `GOOGLE_GENAI_API_KEY`, `BETTER_AUTH_URL`, `POSTHOG_API_KEY`, `CF_R2_*` [user-stated].\n\n## Architectural discipline \u2014 provider neutrality\n\n- AI vendor SDKs are imported only in `@ai-survey/ai` [user-stated].\n- ESLint rule in `apps/web` blocks direct imports of vendor SDKs [user-stated].\n- Result: swap provider without touching app code.\n- Bake-off candidates listed but not yet installed: Anthropic, OpenAI, Fireworks, Groq [user-stated].\n\n## Tradeoffs I would call out\n\n- Vercel AI SDK v6 with `Output.object` trades raw model power for SDK-level validation. Cost: tied to whatever the SDK supports for structured output. Benefit: the discriminated union is enforced at one seam, not scattered across handlers.\n- Temperature 0.3 for structured reliability trades conversational warmth for parse-rate. The system prompt has to carry the warmth.\n- Retry only once, and only on transient failures. Cost: occasional user-visible failure. Benefit: no thundering-herd on a sticky 4xx; no quiet retry on a schema violation.\n- Railway Hobby + Nixpacks trades vendor portability for solo-dev speed. The escape hatch is that nothing in the AI layer is Railway-specific.\n- Pooled vs direct Neon URLs are split deliberately. Migrations bypass PgBouncer; runtime uses it. Cost: two env vars. Benefit: no surprise on prepared-statement edge cases.\n\n## Testing\n\n- Pre-push gate: `pnpm typecheck &amp;amp;&amp;amp; pnpm test &amp;amp;&amp;amp; pnpm test:e2e &amp;amp;&amp;amp; pnpm build` enforced by `.claude/rules/testing-gates.md` [user-stated].\n- Vitest unit + Playwright E2E both run before push; blocking pre-commit hook with no `--no-verify` escape [user-stated].\n- Test mode: `PILOT_TEST_MODE=1` on port 3210 with fixture-driven E2E [user-stated].\n- Test files observed: `apps/web/src/features/pilot-interview/__tests__/chat-handler.test.ts`, `packages/ai/src/__tests__/pilot-response.test.ts`, `packages/ai/src/__tests__/with-timeout.test.ts` [user-stated].\n- Baseline coverage: 0 unit + 0 E2E currently \u2014 project just scaffolded; first tests landing with feature 1 [user-stated].\n\n\n# Feature Evidence \u2014 ai-survey-app\n\n&amp;gt; Note: **actively hunting the paypal moment.** Original wedge (feedback-surface ICP across 11 surfaces) was tested and weakened by my own adversarial audit on 2026-05-14 (Codex + devil-advocate + user research). Current candidate wedge: **estate/probate solo-attorney intake** (confidence medium). 30-day validation in flight: 15 attorney discovery calls + 3 paid concierge pilots. The reversal is product discipline \u2014 pre-registered rubric, honest falsification, immediate re-aim \u2014 not a retreat. The features below describe what shipped technically; see `product-strategy.md` for the active wedge hunt.\n\n## Gaps\n\n- No external respondent data yet. PoC validated by founder + advisor only.\n- 0 unit tests + 0 E2E at baseline (TDD gate exists before tests land).\n- SaaS builder UI not shipped.\n- No paying customers, no pre-sales.\n\nConcrete shipped features. One-liner, location, proof. Ordered by what a recruiter for an AI Product Builder or Senior PM (AI) role would care about first.\n\n## AI features\n\n- **Conversational intake under structured-output discipline** \u2014 `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` wraps Vercel AI SDK v6 `generateText` with `Output.object({ schema, name: 'pilot_turn' })` [src: packages/ai/src/pilot-response.ts].\n- **Per-turn system-prompt regeneration with form goal + ICP + extraction state** \u2014 `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` rebuilds the prompt every turn so the model sees the running extraction [src: apps/web/src/features/pilot-interview/model-input-prompt-sections.ts].\n- **Discriminated-union schema at the SDK boundary** \u2014 `InterviewUiToolSchema` covers `ask_text | ask_single_select | ask_multi_select | ask_confirm | ask_voice | complete_interview` [src: apps/web/src/features/pilot-interview/schema.ts].\n- **Two-stage validation** \u2014 SDK boundary first, then `.superRefine(extractionEmailRefinement)` for cross-field rules [user-stated].\n- **Wire-input strictness** \u2014 `PilotInboundUserMessageSchema.strict()` rejects unknown keys; `id`, `role`, `createdAt` are server-assigned, never trusted from the wire [user-stated].\n- **30-second per-attempt timeout** \u2014 bounded by Vercel AI SDK call options; covered by `packages/ai/src/__tests__/with-timeout.test.ts` [user-stated].\n- **One-shot retry only on transient failures** \u2014 retries on undefined output, 5xx, 429, timeout; never on 4xx (except 429) or unsupported-feature errors [user-stated].\n- **Temperature 0.3 for structured reliability** \u2014 deliberately below conversational ~0.7 [user-stated].\n- **Gemini 3 thinking-mode routing** \u2014 provider config in `@ai-survey/ai`; vendor SDK imports walled off [user-stated].\n- **Provider isolation walled by ESLint** \u2014 vendor SDKs only importable inside `@ai-survey/ai`; only Gemini 3 wired today; no bake-off run yet [user-stated].\n\n## Conversational UX\n\n- **First-turn pre-warmth** \u2014 AI opening renders immediately on widget load; no Start button, no progress bar (Epic 2.10). Proof: `chat-handler.ts` first-turn path [src: apps/web/src/features/pilot-interview/chat-handler.ts].\n- **Anonymous session auto-created on first message** \u2014 no signup wall between the respondent and the dialog. Proof: session creation in handler [user-stated].\n- **Language pre-selected by URL param** \u2014 auto-detect planned but not shipped. Proof: language flow in `chat-handler.ts`; documented gap [user-stated].\n- **Mobile-fixed layout** \u2014 recent fixes addressing overflow. Proof: commits `d20fdce1`, `681f71f4` Fix pilot mobile layout overflow [user-stated].\n- **assistant-ui v0.12.26 + shadcn/ui chat surface** \u2014 Proof: dependency versions [user-stated].\n- **Voice intake variant** \u2014 `ask_voice` is one of the six UI tool variants in `InterviewUiToolSchema`. Voice preference adoption is on the metrics doc. Proof: schema variant name; metrics doc reference [user-stated].\n\n## Persistence\n\n- **`pilot_interviews` table** \u2014 `sessionId`, `createdAt`, `status`, `respondentLanguage` [src: apps/web/src/db/schema.ts].\n- **`pilot_transcript_messages` table** \u2014 `id` uuid, `sessionId` FK, `role`, `content` text, `createdAt` [src: apps/web/src/db/schema.ts].\n- **`pilot_extractions` table** \u2014 `sessionId` FK PK, extraction fields as jsonb / text, `completionScore` [src: apps/web/src/db/schema.ts].\n- **Neon PgBouncer vs direct URL split** \u2014 `DATABASE_URL` pooled at runtime, `DATABASE_URL_DIRECT` for migrations [user-stated].\n\n## Observability\n\n- **PostHog Web Analytics + Session Replay** \u2014 enabled; surveys and flags disabled [commit `631d8482`, user-stated].\n- **PostHog OTel + `PostHogSpanProcessor` server bootstrap** \u2014 [commit `fc017ee1`, user-stated].\n- **PostHog LLM Analytics on chat path** \u2014 env kill-switch and UA consent [commit `65402fd7`, user-stated].\n- **`pilot_chat_turn` event** \u2014 per turn: `latencyMs`, `usage`, `confidence` [user-stated].\n- **`pilot_interview_completed` event** \u2014 per session: `completionScore`, `turns elapsed`, `language`, `confidence` [user-stated].\n- **Awaited captureImmediate in flush** \u2014 a real reliability fix, not a docs change [commit `eb9c8fb7`, user-stated].\n\n## Tests and quality gates\n\n- **Pre-push gate** \u2014 `pnpm typecheck &amp;amp;&amp;amp; pnpm test &amp;amp;&amp;amp; pnpm test:e2e &amp;amp;&amp;amp; pnpm build`. Blocking pre-commit hook; `--no-verify` not allowed by rule. Proof: `.claude/rules/testing-gates.md` [user-stated].\n- **Vitest unit + Playwright E2E both run before push** \u2014 Proof: same gate file [user-stated].\n- **Test mode** \u2014 `PILOT_TEST_MODE=1` on port 3210, fixture-driven E2E. Proof: env flag in handler [user-stated].\n- **Observed test files** \u2014 `apps/web/src/features/pilot-interview/__tests__/chat-handler.test.ts`, `packages/ai/src/__tests__/pilot-response.test.ts`, `packages/ai/src/__tests__/with-timeout.test.ts`, `playwright.config.ts` plus `tests/e2e/` [user-stated].\n- **Baseline coverage: 0 + 0** \u2014 project just scaffolded; first tests landing with feature 1. Gate exists before the tests by design [user-stated].\n\n## Build harness\n\n- **`CLAUDE.md` as SSOT for all AI tools** \u2014 Proof: commit `db3aed35` docs(claude.md): rebuild as single SSOT for all AI tools [user-stated].\n- **Codex integration rules** \u2014 `.claude/rules/codex-integration.md` [user-stated].\n- **Codex findings ledger** \u2014 `docs/retro/codex-findings/YYYY-MM.md` with `caught_by: codex` provenance on every promoted finding. Feeds the `tasks-for-sonnet` trigger catalog via retro Step 3.5 [user-stated].\n\n## Deployment\n\n- **Railway Hobby + Nixpacks** \u2014 auto-deploy on push to `main` [user-stated, `railway.json`].\n- **`preDeployCommand: [\"pnpm -F web db:migrate\"]`** \u2014 migrations run before deploy [user-stated, `railway.json`].\n- **Healthcheck `GET /` with 300s timeout, restart x 3** [user-stated, `railway.json`].\n- **Auth pinned to Better Auth &amp;gt;=1.6.5** \u2014 picks up CVE-2026-41427 fix. Proof: dependency pin [user-stated; CVE id not independently verified].\n- **Cloudflare Turnstile bot protection** \u2014 on the public widget surface [user-stated].\n\n## Public proof\n\n- **Live URL** \u2014 `prototype-with-ai.ianchuk.com`, Ukrainian only, anonymous, public, Cloudflare-proxied [user-stated].\n- **Other gaps** \u2014 no published completion-rate numbers, no eval scoreboard, no customer logos, no compliance certifications [user-stated]. See Gaps section at top for the rest.\n\n\n# Source Index \u2014 ai-survey-app\n\nClaim ledger for the ai-survey-app evidence pack. Every fact in the other six files traces back here.\n\n## Source-backed claims\n\nMost claims in this pack are user-stated rather than file-cited because the source files were not opened in this evidence pass \u2014 the brief described them. Where a commit hash is given, it is a verbatim user-stated commit subject.\n\n- Stack identifiers (TypeScript 6, TanStack Start, React 19, assistant-ui v0.12.26, shadcn/ui, Vercel AI SDK v6, Gemini 3, PostgreSQL via Neon, Drizzle ORM, Zod, oRPC, Better Auth &amp;gt;=1.6.5, PostHog, Cloudflare R2, MinIO, Resend, Mailpit, Turborepo + pnpm, Vite, Railway Hobby + Nixpacks, Cloudflare Turnstile) [user-stated].\n- AI orchestrator path `apps/web/src/features/pilot-interview/chat-handler.ts` [src: apps/web/src/features/pilot-interview/chat-handler.ts].\n- AI call `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` [src: packages/ai/src/pilot-response.ts].\n- Vercel AI SDK call shape `generateText(model, { output: Output.object({ schema, name: 'pilot_turn' }), system, messages, ... })` [user-stated].\n- Schema discriminated union `InterviewUiToolSchema` over `ask_text | ask_single_select | ask_multi_select | ask_confirm | ask_voice | complete_interview` [user-stated].\n- Extraction schema `apps/web/src/features/pilot-interview/schema.ts:PilotExtractionBaseSchema` with the listed fields and `.trim().max(2000)` / `.max(500)` guards [src: apps/web/src/features/pilot-interview/schema.ts].\n- Two-stage validation: SDK boundary + handler `.superRefine(extractionEmailRefinement)` for `contactConsent =&amp;gt; email` [user-stated].\n- Wire input strictness `PilotInboundUserMessageSchema.strict()`; server-assigned `id` / `role` / `createdAt` [user-stated].\n- 30-second timeout per attempt; one retry on undefined / 5xx / 429 / timeout; never on 4xx (except 429) or unsupported-feature errors [user-stated].\n- Temperature 0.3 [user-stated].\n- System-prompt regenerator `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` with sections: opening context, turn instructions, conversation history, output contract, interview state [src: apps/web/src/features/pilot-interview/model-input-prompt-sections.ts].\n- Persistence tables `pilot_interviews`, `pilot_transcript_messages`, `pilot_extractions` in `apps/web/src/db/schema.ts` [src: apps/web/src/db/schema.ts].\n- Pooled vs direct Neon URLs at runtime vs migrations [user-stated].\n- PostHog events `pilot_chat_turn` (`latencyMs`, `usage`, `confidence`) and `pilot_interview_completed` (`completionScore`, `turns elapsed`, `language`, `confidence`) [user-stated].\n- Metrics doc `docs/product/pilot-learning-metrics.md` [user-stated].\n- Pre-push gate `pnpm typecheck &amp;amp;&amp;amp; pnpm test &amp;amp;&amp;amp; pnpm test:e2e &amp;amp;&amp;amp; pnpm build` per `.claude/rules/testing-gates.md`; blocking pre-commit hook with no `--no-verify` escape [user-stated].\n- Observed test files: `apps/web/src/features/pilot-interview/__tests__/chat-handler.test.ts`, `packages/ai/src/__tests__/pilot-response.test.ts`, `packages/ai/src/__tests__/with-timeout.test.ts`, `playwright.config.ts`, `tests/e2e/` [user-stated].\n- Baseline coverage: 0 unit + 0 E2E currently [user-stated].\n- Provider neutrality: vendor SDKs only in `@ai-survey/ai`; ESLint rule in `apps/web` enforces it [user-stated].\n- Bake-off candidates listed but not installed: Anthropic, OpenAI, Fireworks, Groq [user-stated].\n- Deploy: Railway Hobby + Nixpacks; `railway.json` `preDeployCommand: [\"pnpm -F web db:migrate\"]`; `GET /` healthcheck 300s, restart x 3; auto-deploy on `main` [user-stated].\n- Secrets: `DATABASE_URL` (pooled), `DATABASE_URL_DIRECT` (migrations), `GOOGLE_GENAI_API_KEY`, `BETTER_AUTH_URL`, `POSTHOG_API_KEY`, `CF_R2_*` [user-stated].\n- `CLAUDE.md` as single SSOT for all AI tools \u2014 `db3aed35` docs(claude.md): rebuild as single SSOT for all AI tools [user-stated].\n- `.claude/rules/codex-integration.md` Codex integration rules [user-stated].\n- Codex findings ledger `docs/retro/codex-findings/YYYY-MM.md` with `caught_by: codex` provenance, feeding `tasks-for-sonnet` trigger catalog via retro Step 3.5 [user-stated].\n- Live PoC URL `prototype-with-ai.ianchuk.com`, Ukrainian only, anonymous, public, Cloudflare-proxied [user-stated].\n- Recent commits (last 25): `cd78d2c8` Add pilot interview discovery docs; `a96dfa71` docs(agents) carry pilot lessons into saas guidance; `36dcca12` docs(retro) 2026-05-12 retrospective on pilot code lessons; `d20fdce1` and `681f71f4` mobile fixes / Fix pilot mobile layout overflow; `65402fd7` feat(posthog) wire LLM Analytics on chat path with env kill-switch + UA consent; `db3aed35` docs(claude.md) rebuild as single SSOT for all AI tools; `fc017ee1` chore(posthog) wire OTel + PostHogSpanProcessor server bootstrap; `631d8482` chore(posthog) enable Web Analytics + Session Replay; disable surveys + flags; `eb9c8fb7` fix(telemetry) await pending captureImmediate promises in flush() [user-stated].\n\n## User-stated / inferred claims\n\n- Oleksii Yanchuk is sole maintainer; the SaaS builder layer is not yet shipped; the GitHub repo is assumed public at `github.com/yanchuk/ai-survey-app` [user-stated].\n- The product is positioned as a conversational intake widget (shareable link + vanilla JS loader to iframe) [user-stated].\n- Product thesis reverted to draft on 2026-05-14 after the founder's Codex adversarial audit, devil-advocate pass, and user research [user-stated].\n- Current candidate wedge: estate / probate solo-attorney intake, confidence medium [user-stated].\n- Backup wedges held in reserve: septic / well / foundation contractor intake, solo therapist private practice intake [user-stated].\n- Next validation plan: 15 attorney discovery calls + 3 paid concierge pilots in 30 days [user-stated].\n- \"Busy people actually answer\" thesis is unproven outside founder and advisor anecdotes [user-stated].\n- Better Auth pin &amp;gt;=1.6.5 picks up CVE-2026-41427 fix [user-stated]. CVE id not independently verified in this pass.\n\n## Unsafe claims to avoid\n\n- Paying customer count or revenue \u2014 none.\n- Completion-rate numbers, response time, drop-off rate \u2014 not published.\n- Eval scores or accuracy numbers \u2014 no eval scoreboard exists.\n- Compliance posture (GDPR, SOC 2) \u2014 explicitly not certified per the brief.\n- \"First\", \"category-defining\", or \"the future of forms\" framing \u2014 unverifiable and the thesis was just reverted, so doubly inappropriate.\n- Calling the SaaS layer shipped \u2014 it is not.\n- Claiming production scale metrics \u2014 no quantitative production metrics exist beyond the founder PoC.\n\n## Strongest proof artifacts\n\n1. Live URL: `prototype-with-ai.ianchuk.com` \u2014 the only externally verifiable artifact.\n2. `packages/ai/src/pilot-response.ts:generatePilotStructuredResponse()` \u2014 the structured-output call seam.\n3. `apps/web/src/features/pilot-interview/schema.ts` \u2014 the `InterviewUiToolSchema` discriminated union and `PilotExtractionBaseSchema` with field guards.\n4. `apps/web/src/features/pilot-interview/model-input-prompt-sections.ts:formatSystemPrompt()` \u2014 the per-turn prompt regenerator.\n5. `apps/web/src/features/pilot-interview/chat-handler.ts` \u2014 the orchestrator, including `.superRefine(extractionEmailRefinement)`.\n6. `.claude/rules/testing-gates.md` \u2014 the pre-push TDD gate.\n7. Commit `db3aed35` \u2014 `CLAUDE.md` as SSOT for all AI tools.\n8. Commit `eb9c8fb7` \u2014 telemetry `flush()` reliability fix; a real bug caught and fixed, not a docs commit.\n9. `docs/retro/codex-findings/YYYY-MM.md` \u2014 the Codex audit ledger with provenance.\n", "creation_timestamp": "2026-05-16T16:32:11.000000Z"}</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/sighting/600462e6-fbec-4a12-89bb-b9ffd50ec73c/export</guid>
      <pubDate>Sat, 16 May 2026 16:32:11 +0000</pubDate>
    </item>
  </channel>
</rss>
