Soft Launch Plan
_Status_: active — 2025-10-22 _Scope_: Safely soft-launch Weldr with real users while preserving trust and telemetry.
This plan mirrors the “founder’s knife” cut: we only ship the safeguards that prevent data loss, privacy issues, or obvious trust gaps. Everything else waits until after we have production feedback.
---
Command Center
pnpm install && pnpm dev inside the export.
6. Make a manual code change, re-run preview/export.
7. Push to GitHub (verify history metadata).
---
1. Must Fix Before Soft Launch
1.1 Persist Feedback Telemetry
app/api/feedback/route.ts, lib/db/schema.ts, Supabase migrations.// TODO: Store feedback in database at line 21); zero visibility into thumbs up/down usage.message_feedback table (chatId, messageId, userId, sentiment, optional note, createdAt). _Done 2025-10-22 via 0020_message_feedback migration._
- [x] Update the API route to insert rows via Drizzle, accepting optional comment text. _Drizzle upsert w/ tenant enforcement lands in app/api/feedback/route.ts._
- [x] Emit POST /api/feedback failures to Sentry/logs and return status to client. _Route now validates input + reuses structured error logging._
- [x] Add quick admin query (CLI or lib/feedback/service.ts) to review feedback during launch. _pnpm feedback:list --chatId= dumps recent entries from the new service helper._
1.2 Guard DSL Streaming (retry + fallback)
app/(chat)/api/chat/route.ts around the sendEvent failure log (~line 538).sendEvent returns false, the DSL delta is lost with no retries and the UI silently desyncs.dsl_update_buffer table + helper in lib/dsl/dsl-update-buffer.ts).
- [x] Implement at least one retry with exponential backoff (current server retries twice with 250ms backoff).
- [x] On repeated failure, push a message-metadata event instructing the client to show “Preview sync failed — press Regenerate preview” + surface a button.
- [x] Log failures with chatId/messageId so we can trace them later. _Now emitted alongside bufferId every time retries are exhausted._
sendEvent failure (stub to return false) and confirm UI shows fallback + retry occurs; logs capture the incident.1.3 Scope Preview Regeneration by chatId
lib/mcp/handlers/regenerate-preview.ts, /api/preview/worker-tick, preview job queue helpers.chatId filtering to the worker tick path (queue query + drainPreviewJobs). _drainPreviewJobs now accepts chatId and only pulls jobs for that chat._
- [x] Expose /api/preview/regenerate?chatId=... that enqueues work for that chat only. _New API route processes a single chat’s queue and returns processed counts._
- [x] Update MCP handler to call the scoped endpoint and error out if the chat has no pending jobs. _weldr_regenerate_preview now reports when zero jobs were found._
- [x] Add integration test covering “chat A cannot drain chat B jobs”. _tests/integration/preview-regenerate-scope.test.ts seeds two chats and verifies cross-chat isolation._
1.4 Real User IDs in Export History
lib/mcp/handlers/export.ts, app/api/export/{github,vercel}/route.ts, lib/export/export-history.ts.userId: 'mcp-user', so audit logs cannot identify who exported.authPost requests. _Handler now forwards env/user-supplied IDs when triggering exports._
- [x] Update server routes to trust-and-verify the incoming userId (must map to session/tenant). _/api/export/{github,vercel} resolve actors via session, request body, or chat owner._
ExportHistoryService records (for /admin visibility). _History entries now store the resolved actor id._1.5 Enforce Production Safety Rails
scripts/ (e.g., cleanup helpers), docs/ops/runbooks.md (or addendum), and any ad-hoc SQL notebooks.DELETE/TRUNCATE in prod because dev/prod share a Supabase project. One slip nukes customer data.dryRun flags + verbose logging to scripts that mutate tenant/app records so we can preview changes before hitting prod.
- [ ] Gate dangerous scripts behind a CONFIRM_PROD=true env check sourced from .env.local so they cannot run accidentally.
- [ ] Route destructive script logs into admin_audit_log (new helper or reuse existing logging infra) for after-the-fact review.
1.6 Add Redundant Email Capture
lib/db/auth-schema.ts (new important_contacts table + migration), signup handler (lib/auth/signup.ts or NextAuth callbacks), optional webhook client (Zapier/MailerLite).important_contacts (id, email, source, created_at, notes jsonb) with NOT NULL email + uniqueness. _0022_important_contacts migration adds table + auth trigger._
- [x] On signup/profile create, insert into this table within the same transaction; log failures. _createUserProfile now records contacts via recordImportantContact (and fails fast on DB errors)._
- [x] Fire a secondary webhook (MailerLite/Mailchimp/Zapier/Google Sheet) with {email, userId, source} so we have an offsite copy. _recordImportantContact POSTs to CONTACT_BACKUP_WEBHOOK_URL when set and records lastSyncedAt._
- [x] Document a quick export command (pnpm contacts:export) that dumps the table to CSV. _New CLI script streams CSV to stdout._
- [x] Provide a one-off backfill script (pnpm contacts:backfill --dry-run) to mirror existing auth.users rows into the backup table without touching production flows.
important_contacts, 2) webhook receives payload, 3) CLI export prints the email list (pnpm contacts:export --limit=1).1.7 Manual Backup & Weekly Automation
scripts/db/export-critical-tables.ts (new), cron/GitHub Action config, docs/soft-launch-plan.md appendix for instructions.users, apps, dsl_snapshots, etc. Supabase free tier offers no retained backups.pg_dump to export critical tables; store artifacts in a private, versioned location (Drive/S3/repo).
- [ ] Script: pnpm tsx scripts/db/export-critical-tables.ts --dest=s3://... that selects the same tables and uploads to secure storage.
- [ ] Schedule weekly automation (GitHub Action or cron on Fly/Render) with service-role creds to run the script and alert on failures.
- [ ] Document restore instructions in the appendix.
--dry-run option.1.8 “Preview / No Guarantees” Copy
app/(marketing)/layout.tsx or components/Footer.tsx), workspace dashboard (app/(chat)/layout.tsx), localized strings.PreviewEnvironmentBanner renders in the chat layout with export + FAQ links and can be dismissed per browser._
- [x] Add a small badge near the logo (“Preview”) for visual reinforcement. _Footer brand now renders a persistent Preview pill adjacent to the Weldr logo._
1.9 Schema Health Check & Audit Log
lib/db/schema.ts (ensure email columns are NOT NULL, review FK cascades), new event_log table + helper in lib/audit/event-log.ts.ON DELETE CASCADE; replace with RESTRICT where user/app data is at risk.
- [ ] Ensure email columns in auth/profile tables are NOT NULL and validated.
- [ ] Add event_log (id, user_id, type, payload jsonb, created_at) and log signup, app creation, exports, admin scripts.
- [ ] Provide a simple pnpm audit:recent --type=admin_action command for ops review.
1.10 Supabase Plan Decision
docs/ops/infra.md.---
2. Should Fix within 72 Hours
2.1 Remove or Flag Mock Vercel Deployments
https://${appId}.vercel.app without creating a deployment (lib/generation/generation-service.ts:167-196).2.2 Run DB-dependent Tests Once
tests/custom-code/custom-store.test.ts (needs RUN_CUSTOM_STORE_TESTS=true + DB).
- tests/db/tenant-rls.test.ts (needs POSTGRES_URL and non-CI env).
2.3 Minimal Launch Asset Pack
business-docs/press-kit-checklist.md; this is the trimmed MVP.---
3. Post-Launch / Nice to Have
---
Appendix
POSTGRES_URL= (non-pooler).
- RUN_CUSTOM_STORE_TESTS=true.
- Supabase service role key loaded in .env.local if tests touch auth claims.
Keep this doc updated as tasks land. Mark each [ ] as [x] once complete and add short verification notes inline. When the “Must Fix” section is fully checked, we’re clear to soft-launch.* End Patch