Release 0.13.0-alpha #39
Reference in New Issue
Block a user
No description provided.
Delete Branch "staging"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
any[]stateChanges
stats.tswith factory pattern usinguseSWR; dashboard sections load independently with background refresh and tab-aware polling (stats.ts,dashboard.ts,[id]/page.tsx)ContentStats,Locations,TechSpecs,TopReferrers)SettingsPageClient.tsx,SecurityActivityCard.tsx,TrustedDevicesCard.tsx)auth.ts,refresh/route.ts), cross-tab sign-out sync, session expiration warning, auth context effect deps stabilized (context.tsx)ciphera.net,*.gstatic.com,google.comtoimg-srcandconnect-src; ESM import for next-pwa (F-5); removed invalid icon files (next.config.ts).github/workflows/test.yml,vitest.config.ts)X-Request-IDpropagated across frontend and backend (requestId.ts,client.ts)getCookieDomainutility (cookies.ts); login page loading overlay (login/page.tsx)YYYY-MM-DDacross all analytics (funnels.ts)PasswordInput,WebsiteFooter,WorkspaceSwitcher,Countries,TopPages,errorHandler; removed invalid PWA icon files@ciphera-net/uito^0.0.79,@types/reactto v190.13.0-alpha; changelog reorganized with correct categoriesTest Plan
npm run testandnpm run buildpassGreptile Summary
This is a large quality-of-life release that migrates dashboard data-fetching from manual
useState/useEffect/setIntervalpatterns to SWR, collapses ~13 near-identical fetch functions into a factory pattern, and adds CSP/CORS hardening, a shared cookie-domain utility, and refresh token plumbing.Key changes and findings:
app/sites/[id]/page.tsx,lib/swr/dashboard.ts): Dashboard sections now fetch independently with SWR, eliminatingany[]state and manual polling. The lazy-initializer pattern fordateRangeavoids the previous double-fetch on settings restore. Looks correct overall, with one minor prop-type concern onExportModal(topPages/topReferrerscan beundefinedbefore the first fetch).lib/api/funnels.ts— potentially breaking:getFunnelStatswas changed from sendingfrom/toRFC3339 timestamps tostart_date/end_dateYYYY-MM-DD strings. The original conversion logic was added deliberately and the funnel stats endpoint may have a different API contract than the dashboard/stats endpoints. If the backend hasn't been updated simultaneously, funnel date-range filtering will silently break.lib/api/stats.ts: ThecreateListFetcherfactory andbuildQueryhelper are a clean, correct refactor with no behavioral changes to callers.next.config.ts):'unsafe-inline'is present unconditionally inscript-src. While this is a practical necessity for the current Next.js setup without nonce support, it should be noted that this effectively nullifies thescript-srcallowlist for XSS mitigation in production.step.step.namewhich could collide for user-named steps with identical names;step.step.orderwould be safer.context.tsx, cookie-domain deduplication, and removal of client-side SHA-256 session identification are all clean improvements.Confidence Score: 3/5
lib/api/funnels.tschange, which silently alters both the parameter names and format sent to the funnel stats backend endpoint — if the backend hasn't been updated in lockstep, funnel date filtering will stop working in production without any visible error.lib/api/funnels.ts— confirm the backend funnel stats endpoint now acceptsstart_date/end_date(YYYY-MM-DD) rather thanfrom/to(RFC3339).Important Files Changed
from/to(RFC3339) tostart_date/end_date(YYYY-MM-DD) — potentially breaking if the backend endpoint hasn't been updated to match.createListFetcherfactory and a sharedbuildQueryhelper, with no behavioral changes to the public API surface.useState<any[]>with typed SWR hooks; minor issue:topPages/topReferrerspassed to ExportModal can beundefinedbefore first fetch.useCampaignshook and propagatesintervalthroughuseDashboardOverview; clean SWR config with appropriate dedup/refresh intervals.'unsafe-inline'inscript-srcis required by Next.js but renders that directive largely ineffective for XSS prevention in production.step.step.name; minor risk of duplicate keys if user creates two steps with the same name.Sequence Diagram
Last reviewed commit:
564c85335 files reviewed, 4 comments
Edit Code Review Agent Settings | Greptile
@@ -280,3 +280,3 @@{stats.steps.map((step, i) => (<tr key={i} className="hover:bg-neutral-50 dark:hover:bg-neutral-800/30 transition-colors"><tr key={step.step.name} className="hover:bg-neutral-50 dark:hover:bg-neutral-800/30 transition-colors"><td className="px-6 py-4">Duplicate-key risk if two funnel steps share a name
step.step.nameis user-supplied. If a user creates two funnel steps with the same name (e.g. two "Homepage" steps), React will emit a duplicate-key warning and produce incorrect DOM reconciliation.A safer key combines the stable
orderfield (which is unique by definition in a funnel) with the name, or simply usesstep.step.orderalone as the key.Prompt To Fix With AI
Breaking API contract change for funnel date parameters
The old implementation explicitly converted
YYYY-MM-DDstrings into RFC3339 boundaries (T00:00:00.000Z/T23:59:59.999Z) and sent them asfrom/toquery params. This PR replaces that withstart_date/end_datein plainYYYY-MM-DDformat — both the parameter names and the format have changed.If the backend funnel stats endpoint (
/sites/:id/funnels/:funnelId/stats) still expectsfrom/towith RFC3339 timestamps (distinct from the dashboard/stats endpoints that usestart_date/end_date), date-range filtering on funnel reports will silently fail — the endpoint will either ignore unrecognized params and return all-time data, or return an error.The original
toRFC3339Rangehelper andDATE_ONLY_REGEXwere very deliberately added, suggesting the backend had a different contract for this endpoint. Please confirm the backend was updated in lockstep, or revert to the previous parameter names and format if not.Prompt To Fix With AI
@@ -8,0 +16,4 @@"img-src 'self' data: blob: https://www.google.com https://*.gstatic.com https://ciphera.net","font-src 'self'",`connect-src 'self' https://*.ciphera.net https://ciphera.net https://www.google.com https://*.gstatic.com https://cdn.jsdelivr.net${process.env.NODE_ENV === 'development' ? ' http://localhost:*' : ''}`,"worker-src 'self'",'unsafe-inline'in productionscript-srcneutralises XSS protectionThe comment acknowledges this is required for Next.js bootstrap scripts, but browsers ignore the entire
script-srcallowlist when'unsafe-inline'is present (unless a nonce or hash is also provided). This means thescript-src 'self'restriction has no effect in production — any inline script injected by an attacker will execute freely.The recommended approach for Next.js is to use a per-request nonce (via
generateBuildId/ middleware) and emitscript-src 'nonce-{value}'rather than'unsafe-inline'. That is non-trivial to set up, but as long as'unsafe-inline'is present thescript-srcdirective is essentially no-op from a security standpoint. At a minimum, this is worth a code comment so future contributors don't assume XSS protection is in force.Prompt To Fix With AI
Additional Comments (1)
app/sites/[id]/page.tsxtopPages/topReferrerscan beundefinedduring initial loadPreviously these were initialized with
useState<any[]>([])and were therefore always defined arrays. With SWR they areundefineduntil the first fetch completes. IfExportModaldeclares those props asTopPage[]/TopReferrer[](non-optional), TypeScript will accept them today (the optional-chaining returnsundefined, which passes through), but the component will receiveundefinedat runtime instead of an empty array and may call.map()on it, throwing.Add a fallback to keep the contract consistent:
Prompt To Fix With AI