March 14, 2026

Branded email verification, onboarding reliability fix, visual regression testing, accessibility improvements, security hardening, and full-funnel analytics.

Branded email verification for new accounts, onboarding reliability fix, visual regression testing with Argos CI, accessibility improvements for screen readers, production database locked to private-only networking, contact form email delivery, reliability fixes for RFP generation and billing, persistent RFP conversations, unified status transitions, review accuracy improvements, faster RFP chat, search indexing fixes, security hardening, full-funnel analytics tracking, unified structured logging, and database query caching.

New

  • Branded email verification for new accounts. New email/password sign-ups now receive a branded verification email matching the Strutter design language instead of a generic system email. The "check your email" interstitial page includes a resend button, and sign-in displays a success banner after verification. No session is created until the email address is confirmed.

  • Contact form email delivery. The contact form on strutterai.com now forwards submissions to the team inbox. Each notification includes the sender's name, email, company, and message in a branded email template matching the rest of the platform's communications.

  • Visual regression testing with Argos CI. Every pull request now captures screenshots of key workflows and compares them against the baseline to catch unintended visual changes. Sixteen visual checkpoints cover smoke tests, RFP lifecycle, onboarding, the vendor portal, and navigation. Argos CI provides a side-by-side comparison dashboard so reviewers can spot layout shifts, styling regressions, and rendering differences before they reach production.

Fixed

  • Onboarding no longer loops back after completing setup. Finishing the onboarding wizard could redirect you back to the onboarding page instead of forwarding to the dashboard. Navigation now performs a full page load after setup, ensuring you land on the correct destination. The submit button also reliably resets if an error occurs.

  • Production sign-in restored. A networking change that restricted the database to private access also blocked the application from reaching it, preventing all sign-ins. Connectivity has been restored through private VPC networking, and SSO domain detection now works correctly during sign-in.

  • Strutter AI review now reads full RFP content. The AI review prompt was receiving raw document data instead of readable content, which degraded review quality. Reviews now process the fully rendered document for more accurate and relevant feedback.

  • RFP sections preserved during AI review corrections. When Strutter AI corrected a generated RFP, all sections were collapsed into a single block, losing the original structure. Corrections now maintain each section's boundaries and headings.

  • Question generation errors now surface clearly. When Strutter AI failed to generate questions for some sections, the failures were hidden. The system now detects and reports generation gaps so you can fill in missing questions manually.

  • Score display uses the correct scale. RFP scores showed a scale of 1 to 100, but the actual scoring range is 1 to 10. The display now matches the true scale.

  • Corrected database credentials in the example environment file. The example environment file listed an outdated database name and user. It now shows the correct values, so new developers and fresh deployments start with the right configuration. A regression test prevents this from drifting again.

  • Notifications no longer fire for unrelated RFP edits. Editing an RFP's title, adding questions, or making other routine changes could trigger false "published," "closed," or "awarded" notifications. Notifications now only fire when the RFP status actually changes.

  • Faster search with cached query embeddings. Repeated searches and chat queries no longer make redundant calls to the embedding service. Query embeddings are now cached briefly and deduplicated when multiple requests arrive at the same time, reducing search latency.

  • Vendor scores in search reflect manual overrides. When a human override score existed for a vendor response, the search index still stored the original Strutter AI score. Search results and recommendations now use the same score the rest of the system displays.

  • Generated RFP content now appears in search results. RFP body content created through Strutter AI was not being indexed for search because the indexer did not understand the rich text document format. Search now processes the full document structure, so generated content is discoverable.

  • RFP generation no longer stalls on internal errors. If the background job queue rejected a generation request, the RFP stayed in a permanent "Generating..." state with no way to retry. The system now detects the failure, cleans up the incomplete draft, and surfaces the error so you can try again.

  • Chat credits are no longer consumed for invalid requests. Sending a chat message referencing an RFP that no longer exists would deduct credits before the system checked whether the RFP was valid. Credits are now only consumed after the request is fully validated.

  • Marketing site navigation menu renders reliably. A React hook ordering issue in the site header's dropdown menu caused lint failures and could produce inconsistent rendering in certain browsers. Hooks now execute unconditionally before any early returns.

  • Generation jobs no longer run more than once. Under certain retry conditions, the same generation job could execute twice, producing duplicate content. Each job now claims exclusive ownership before it starts, preventing overlapping runs.

  • RFP chat conversations now persist across sessions. Chat messages on RFP pages were routed to the general chat endpoint, so conversation history was lost on page refresh. The prompt bar now routes to the per-RFP conversation endpoint, and messages are saved to the database and reload when you return to the page.

  • Strutter AI chat now sends award notification emails. Awarding an RFP through chat skipped the award notification email that the REST API sent. Both paths now use the same status transition service, so award emails, auto-saving questions and vendors to libraries, and award notes all work consistently regardless of how the status change is triggered.

  • No more 404 errors when creating a new RFP. Navigating to the new RFP page triggered a spurious 404 in the browser console because the prompt bar mistakenly treated the URL path /rfps/new as an existing RFP ID and tried to load its conversation history. The prompt bar now recognizes the creation page and skips the data fetch.

  • Faster Strutter AI chat on mature RFPs. RFP conversations with many turns and questions became progressively slower because the chat prompt included the full history and all question text on every request. Strutter AI now focuses on the most recent messages and summarizes question context, significantly reducing response times for long-running conversations.

  • Screen reader support for chat and RFP creation. The chat input, send button, and RFP description field now have proper labels for screen readers. The loading spinner announces its status to assistive technology, and the RFP editor overview toggle is correctly linked to its collapsible content.

Improved

  • Conversational progress indicator for RFP generation. The "Researching your request" spinner now renders as a chat message bubble with a Strutter AI avatar, matching the conversational style used by the rest of the wizard. Your original prompt also appears above the progress indicator for context.

Security

  • Database security. Production database restricted to private-only networking with encrypted connections enforced. Database credentials are retrieved from a secrets manager at runtime.

  • Access controls strengthened. Tightened authorization checks including admin-only data export and organization status validation for API keys.

  • Vendor claims now verify account identity. Vendor invitation claims now require the signed-in account email to exactly match the invited email before any vendor organization link or membership is created.

  • Email/password sign-up now waits for email verification. Email/password accounts must verify their email before they can create an app session or continue into onboarding flows that create organization membership. Verification tokens are single-use and time-limited. The verification endpoint is rate-limited and returns consistent responses regardless of whether the email exists, preventing account enumeration.

  • Invite-based onboarding now requires the secure invite link. Team membership is no longer granted from email-only onboarding detection. Joining an existing organization must be completed from the invitation link sent to that email address.

  • Admin organization deletion is owner-safe. Organization deletion now resolves the current owner inside the organization before removing any Firebase account, preventing stale owner pointers from deleting users in another tenant.

  • Canonical organization owners cannot be moved without reassignment. Admin user moves now reject attempts to move the user referenced as the organization owner, preventing stale ownership pointers and broken tenant state.

  • Contact form protected against spam and abuse. The contact form now enforces rate limits, validates input fields, rejects oversized payloads, and detects bot submissions. Raw message content is no longer written to server logs.

  • Upload and chat endpoints enforce payload size limits. Vendor file uploads and Strutter AI chat requests now reject oversized payloads before processing begins, preventing resource exhaustion from abnormally large requests.

  • Vendor portal access restricted to approved members. The vendor portal now rejects access from pending team members who have not yet been approved. RFP detail pages, response submissions, and exports all verify the vendor's approval status and invitation before granting access.

  • Vendor conversations scoped to the correct RFP. Vendor message threads now verify that both the thread and the vendor belong to the same RFP, preventing cross-RFP data access through thread manipulation.

  • Signed file URLs no longer stored in responses or exports. File references in vendor responses and exports now use permanent storage paths instead of temporary signed URLs. Existing responses with embedded signed URLs are automatically scrubbed during export.

  • SSO provider details no longer exposed on public endpoints. The unauthenticated domain detection endpoint no longer returns internal provider identifiers. SSO provider details are now served through a separate, rate-limited endpoint that requires context.

  • Vendor thread metadata now scoped to visible messages. Thread message counts and ordering reflect only vendor-visible activity, preventing internal discussion details from leaking into the vendor portal.

  • Rate limiting now uses the correct client IP. Rate limits are applied using the true client IP from the load balancer forwarding headers, closing a loophole that allowed IP spoofing to bypass rate limits.

  • Organization domains are now unique and validated. Each organization domain must be unique across the platform, preventing domain squatting. Free email domains (Gmail, Yahoo, etc.) are blocked from use as organization domains.

  • Admin actions now include actor attribution in audit logs. Break-glass admin operations record the acting admin's identity with clear actor and target separation, strengthening compliance and audit trail coverage.

  • Third-party updates. Patched dependencies flagged by security audits.

Analytics

  • Full-funnel GA4 event tracking. Added 10 new GA4 event definitions covering the entire RFP activation funnel: RFP creation, publishing, vendor invitations, vendor response submissions, AI-assisted editing, AI chat, AI prefill, RFP close, AI recommendation views, and portal response submissions. Each event carries typed parameters (e.g., question count, RFP ID, vendor count) for granular reporting in Google Analytics. All events are wired into their respective UI components and covered by test assertions.

Under the Hood

  • Removed a hardcoded production address from a tracked configuration file.
  • Migrated input validation on six API routes to schema-based validation for consistent, type-safe request handling.
  • Added deletedAt field to Organization model for soft-delete support.
  • Search chunk storage now enforces uniqueness constraints and uses upsert semantics, making indexing safe under concurrent or retried operations.
  • Vendor response chunks are automatically re-indexed after scoring completes, ensuring search results always reflect the latest score metadata.
  • Extracted a unified RFP status transition service, consolidating duplicated logic from the REST API and Strutter AI chat into a single module. All status changes now follow the same path with full side-effect parity (notifications, library auto-saves, award notes).
  • Marketing site now includes its own email sending capability, keeping it decoupled from the main application's email infrastructure.
  • Synced package-lock.json to resolve lockfile drift after dependency patches.
  • Unified structured logging. Consolidated all server-side logging to a single zero-dependency JSON logger. Replaced ~60 inconsistent log calls across middleware, queue handlers, webhooks, and API routes with structured output that includes severity, timestamps, and trace context.
  • Improved error visibility. Fixed silent catch blocks in auth session and queue handler code that were swallowing errors without logging. All error paths now emit structured log entries.
  • Removed 711 lines of dead code from an obsolete chat tab component that was superseded by the unified prompt bar.
  • Strutter AI chat requests for mature RFPs now use significantly less processing, reducing per-request cost and latency for long-running conversations.
  • Database query performance improvements with optimized composite indexes for common access patterns.
  • Frequently accessed database queries for directory search, notifications, and organization lookups are now cached with automatic invalidation on writes, reducing database load and improving response times.
  • Automated accessibility testing now runs against key UI components, catching missing labels and ARIA violations before they reach production.
  • RFP generation now validates research data at runtime, falling back to fresh research if the data shape is unexpected. This prevents silent failures when cached research is stale or malformed.
  • Integrated @argos-ci/playwright into the E2E test suite with the Argos reporter configured to upload screenshots only in CI. Sixteen argosScreenshot() calls across five test files establish the initial visual baseline.
  • Added end-to-end sign-in flow tests covering the happy path (email entry, password entry, redirect to dashboard), invalid password error state, and the forgot password reset form. Five Argos visual regression screenshots capture each key sign-in state. Tests use the actual UI flow rather than API-level cookie bypass and skip gracefully when E2E credentials are not configured.
March 14, 2026 | Strutter AI