Skip to main content

Phase 1 Post-Upgrade Fixes

Completed: 2026-04-02 | PRs: #511, #512, #513, #514, #515, #516 Scope: equa-web repository | Branch: main

Overview

This release gathers the six PRs that landed on equa-web between 2026-03-30 and 2026-04-02, immediately following the Phase 1 frontend ecosystem upgrade. Each PR was scoped tightly to a single fix or small feature; grouping them here gives a single release-note page for the post-upgrade stabilisation work.

Build and Dependencies

@babel/core Upgrade (PR #511)

Webpack builds on every branch were failing with TypeError: api.assumption is not a function. The hoisted @babel/core was pinned at 7.11.6 (pulled in transitively by @svgr/webpack) while @babel/preset-env sub-dependencies required api.assumption(), introduced in 7.13.
PackageBeforeAfter
@babel/core7.11.67.29.0
@babel/plugin-proposal-class-propertiespresentremoved (dead dep, not referenced in .babelrc)
core-jsduplicated entriesdeduplicated + alphabetized
Verification: npx webpack --mode production — 0 errors after upgrade (1 error before).

Features

Dashboard Empty State + Gateway Token Sync (PR #512, Spec 001)

PR #512 was split into two independent workstreams targeting the open issues #502 and #503. Workstream A — Gateway Token Sync (#502) equa-web/src/modules/equabot-settings/services/storage.ts now recognizes ?equabotToken=<token> and ?gatewayToken=<token> in the URL query string, persisting the token to localStorage under the gateway-token key. This matches the standard equabot dashboard --no-open handoff pattern and eliminates the client/server token desync class of bug. Workstream B — Dashboard Empty State (#503) A new DashboardEmptyState component lives at modules/organization-dashboard/components/empty-state/empty-state.tsx. When every rolling metric on the organization dashboard resolves to zero, the dashboard renders a 3-step onboarding guide (create cap table, invite team, upload documents) instead of a page full of zero values. The sibling RecentActions component replaced its 6-year-old “Coming Soon” placeholder with a “No recent activity” empty state. See Spec 001 §2.7 for the token contract and Spec 020 § Post-Onboarding Dashboard Empty State for the component.

Lint follow-up (PR #513)

Three ESLint errors in storage.test.ts (added in #512’s review fixes) were cleaned up. 10 storage tests pass.

Bug Fixes

Network Errors No Longer Freeze the Splash Screen (PR #514, issue #482)

baseRequest() in src/service/lib/http-client.ts previously had no try-catch around fetch(). When the backend was unreachable (network error, DNS failure, CORS blocked), fetch() threw a TypeError that propagated as an unhandled rejection. Redux-loop never got a chance to dispatch the failure action, getCurrentUser’s callback never fired, and the app hung on the Equa logo spinner forever. Fix: Wrap fetch() in try-catch. Network errors now return HttpError(ResponseCode.other, 'networkError', ...) following the same contract as 4xx/5xx responses. The normal error flow proceeds and the app renders the login page instead of hanging. See Frontend Architecture § Network Error Handling for the caller contract.

E2E Auth Form Locators (PR #515, issue #494)

Five regression tests broke after Phase 0 (PR #465). Root cause: test locators targeted input[type="email"], but the actual auth forms use <input type="text"> with react-final-form custom field components. The locators never matched, so the tests timed out at 30s. Fixed files:
  • e2e/auth-modal-security.spec.ts — registration email locator uses name="email"
  • e2e/regression-fixed-issues.spec.ts — login uses name="usernameOrEmail", registration uses name="email"
  • e2e/visual-regression.spec.ts — replaced type="email" with placeholder-based selectors
See Spec 001 §2.6 for the full auth-form field contract so future tests don’t regress.

Infrastructure

Railway / CI Cleanup (PR #516)

nginx.conf — dynamic PORT: listen 8080 was changed to listen ${PORT} with envsubst templating at container startup. Railway injects $PORT per service instance; the hard-coded 8080 had worked only because it happened to match the Dockerfile EXPOSE. Local docker run still defaults to 8080 via the Dockerfile ENV PORT=8080. ci.yml — stale references removed:
  • staging removed from push/pull_request triggers (default branch is now main)
  • GH_PATTERNLIB_TOKEN: placeholder env override removed from the lint-and-build job — the repo-level secret-validation step handles the token properly
Remaining manual cleanup (not in this PR): Delete the stale test domain showing “Waiting for DNS update” in the Railway dashboard, and the 7-year-old production GitHub deployment environment artifact. See Deployment Infrastructure § Frontend Nginx and CI/CD Pipeline § equa-web CI for the updated configs.

Verification

CheckResult
Webpack production build (PR #511)Pass (api.assumption error resolved)
Jest unit tests (PR #512, #513)52 + 10 storage tests passing
Playwright E2E with new locators (PR #515)5 previously broken tests green
Network error path returns HttpError (PR #514)Verified manually — app renders login page instead of splash
Railway dynamic PORT (PR #516)Container boots with Railway-assigned port

What’s Next

Phase 1 PR 3 (pending) — deprecated pattern cleanup covering the 19 remaining issues from the Phase 1 QA audit (legacy lifecycle methods, class component migrations, deprecated API usage).