My earlier estimate of 34 errors was wrong, and the reason is worth
recording: tsconfig carried "strictNullChecks": false as a duplicate key
AFTER the strict flag, and an explicit option beats the strict umbrella
even when --strict is passed on the CLI. So the measurement that produced
34 had silently excluded every null-safety error. The real number was 63.
Both duplicate keys are gone; strict: true now stands alone.
Most were implicit-any, but strict caught several genuine type lies:
- SendSmsPayload.deviceId and WebhookData._id were optional while both
are interpolated into request paths, so an absent value would have hit
/gateway/devices/undefined/send-sms or PATCH /webhooks/undefined.
- webhook-table's deviceName was typed string while buildDeviceLabel
returns string | string[] and the Device cell already renders the
array case. The type never described what the code produced.
- webhooks-section read `webhooks?.data?.length > 0`, comparing
undefined against 0 while the query was still in flight.
- app-header declared a non-null Session while its own body guarded with
session?.user throughout. Making the type honest surfaced four
genuinely unguarded accesses.
- api-keys kept a local ApiKeyRow duplicating the shared ApiKey type, so
the list callback annotated rows as one type while the hook returned
the other. ApiKeyRow is now an alias and the two extra fields moved
onto ApiKey.
- The notifications envelope typed its rows as unknown[], so the
deliveries table's row type went entirely unchecked. Now a real
WebhookNotification type.
The react-hook-form cluster (20 of the 63) was one root cause: zod's
.default() makes the input and output types differ, so z.infer (the
output) is not what the resolver takes. Fixed by typing the forms with
z.input and z.output separately, which changes nothing at runtime.
Also bumped target es5 to ES2017, which fixes the Set-iteration error
that made tsc --noEmit fail before any of this. Next compiles browser
output via SWC and its own browserslist, so bundle targeting is
unaffected. Added @types/papaparse and @types/react-syntax-highlighter,
and a typecheck script, since next build does not check test files.
No @ts-expect-error and no new any were used.
Verified: typecheck clean, build clean, 0 lint errors (21 warnings,
unchanged), 155 unit tests, 78 e2e.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Next 16 removed the `next lint` command, so `pnpm lint` was broken. Replace
.eslintrc.json with an ESLint 9 flat config (eslint.config.mjs) that spreads
eslint-config-next's native core-web-vitals flat config, and point the lint
script at `eslint .`.
Keep Next 16's newer react-hooks (v6) compiler-adjacent rules advisory (warn)
rather than blocking, since they flag working-but-non-optimal patterns across
the existing codebase. `pnpm lint` now passes (0 errors, warnings only).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- remove unused deps: prisma (no schema/usage), tailwindcss-animate
(replaced by tw-animate-css), @radix-ui/react-separator (no imports)
- drop unused DATABASE_URL from .env.example
- bump Radix, react-query, react-table, next-auth, next-themes,
react-hook-form, react-dropzone, tailwind-merge, axios, uuid, etc.
- pin three packages off their newest majors to avoid churn outside this
scope (revisit later):
- lucide-react 0.577 (1.x removes brand/social icons still used in 6 files)
- zod 3.25 (4.x changes resolver input/output typing across all forms)
- react-day-picker 9 (10.x changes the classNames API in ui/calendar)
Build, unit tests, and e2e all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CSS-first config: @import "tailwindcss" + @theme inline mapping the
shadcn HSL tokens; colors unchanged (rebrand lands in the design part)
- switch postcss to @tailwindcss/postcss, drop autoprefixer
- replace tailwindcss-animate with tw-animate-css for the animate-in /
data-state utilities the Radix primitives rely on
- remove tailwind.config.js (v4 auto-detects content) and point
components.json at the CSS
- suppressHydrationWarning on <html> for the next-themes class swap
Build, unit tests, and e2e all green; generated CSS verified to contain
bg-primary, the brand ramp, border-border, and the accordion/animate utilities.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- next 14.2 -> 16.2, react/react-dom 18 -> 19, eslint 8 -> 9,
typescript-eslint 6 -> 8, typescript 5.3 -> 5.7, @types/react* -> 19
- remove i18n config from next.config.js (unsupported in App Router; it
forced a pages-router _document and broke the 404 prerender)
- Next 16 reconfigured tsconfig (moduleResolution bundler, jsx react-jsx)
Build, unit tests, and e2e all green on the new stack.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Establish the testing safety net for the web dashboard before refactoring.
- Vitest + React Testing Library + jsdom for unit/component tests
- MSW node server mocks the API; unhandled requests throw so tests can
never reach a real backend
- Playwright e2e boots the real Next app but intercepts every /api/v1 call
with shared fixtures, and mints a NextAuth session cookie to run authed
- Shared fixtures in test/fixtures.ts back both layers
- Seed tests: Button unit tests, MSW sanity checks, and a dashboard e2e
happy path plus an auth-guard redirect
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* webhook notifications for sms sent, sms delivered, sms failed, and unknown state, events
* updated deliverNotification function to deliver notifications for all events
* removed sms-status-updated filter
* updated payloads based on event type
* updated payloads based on event type
---------
Co-authored-by: Israel Abebe <vernu1997@gmail.com>
* created the webhook notification history page and backend end point
* updated implementation and resolved comments
* updated sms-modal
* updated sms-modal