feat(prerender): scope domain-wide suggestion and top-page filtering to site subpath#2559
feat(prerender): scope domain-wide suggestion and top-page filtering to site subpath#2559dhavkuma wants to merge 3 commits into
Conversation
…to site subpath For subpath sites (e.g. nba.com/kings), the prerender audit was hardcoding allowedRegexPatterns=['/*'] and pathPattern='/*' in the domain-wide suggestion, which would instruct the CDN to prerender the entire domain rather than just the registered subpath. Organic top-page URLs from SiteTopPage (via GSC) could also bleed in domain-wide entries for subpath sites. - getSitePathPattern(baseUrl): derives the correct glob (e.g. '/kings/*') from the site's base URL pathname; root sites continue to get '/*' - isUrlUnderSiteBase(url, baseUrl): filters organic top-page URLs to the subpath; no-op for root sites - getDomainWideSuggestionUrl: labels subpath sites as 'All Subpath URLs' Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Duplicated PR. Original PR : #2500 |
There was a problem hiding this comment.
Hey @dhavkuma,
Strengths
src/prerender/handler.js:45-55-isUrlUnderSiteBasehas clean path-prefix matching. ThestartsWith(${normalized}/)check with the trailing slash correctly prevents false positives like/kingstonmatching/kings. The early return for root sites makes the no-op case explicit.src/prerender/handler.js:27-35-getSitePathPatternhandles trailing-slash normalization correctly, preventing double-slash patterns like/kings//*.src/prerender/handler.js:341-346- Filter placement before.slice(0, limit)is correct. Subpath sites get the top N URLs that belong to this site, rather than top N with out-of-scope ones removed afterward (which could silently return fewer results).- The approach of deriving scope from the existing
baseUrldata model (rather than introducing new config or site properties) is architecturally sound - zero new state, zero migration needed. - PR description is excellent - clearly articulates both bugs, explains what was already working, and provides a concrete test plan.
Issues
Important (Should Fix)
1. Tests absent for new production logic
The PR adds three new helper functions (getSitePathPattern, isUrlUnderSiteBase, rewritten getDomainWideSuggestionUrl) with non-trivial URL parsing and path-matching logic, plus integration changes in getTopOrganicUrlsFromSeo and prepareDomainWideAggregateSuggestion. No test files are modified or added. The PR description itself lists four unchecked test items, confirming these are needed but not yet written.
This is a bug-fix PR addressing a critical production issue (wrong CDN rule scope). Shipping without tests means the fix is unverified and could regress silently.
How to fix: Add unit tests covering at minimum:
getSitePathPattern: root URL, subpath URL, trailing-slash subpath, invalid URLisUrlUnderSiteBase: URL matching subpath, URL outside subpath, root site (no-op), URL exactly equal to basePath, invalid URLsprepareDomainWideAggregateSuggestionwith a subpath baseUrl, assertingpathPatternandallowedRegexPatternsreflect the subpath
2. //todo:dhavkuma debug markers committed on unchanged lines
src/prerender/handler.js:741, src/prerender/handler.js:1110, src/prerender/handler.js:1510, src/prerender/handler.js:1724 - Four personal TODO comments are appended to lines with no functional change. They communicate nothing actionable to future readers and make the PR look unfinished. If these mark pending work, capture it in a follow-up ticket. If they're leftover investigation markers, remove them.
Minor (Nice to Have)
3. Silent catch blocks in new helpers
src/prerender/handler.js:15-17, src/prerender/handler.js:32-34, src/prerender/handler.js:52-54 - All three helpers catch URL parsing failures and return safe defaults without logging. The fallback choices are defensively correct (fail-open), but if site.getBaseURL() ever returns an invalid URL, you'll have no signal that a site record is corrupted until someone notices the CDN rule is too broad. The helpers don't have access to log so this is a design tradeoff, not a blocker.
Recommendations
- Coordinate with PR #2500 (flagged as a duplicate by ssilare-adobe, still open). Whichever lands second will have merge conflicts in the same functions. Resolve which PR moves forward before either merges.
- Validate that the downstream CDN consumer interprets
allowedRegexPatternsvalues (e.g.,/kings/*) as globs rather than raw regex. Characters valid in URL pathnames (parentheses, dots) could produce overly-permissive patterns if the field is interpreted as regex.
Assessment
Ready to merge? No
The core logic is correct and well-implemented, but the PR ships zero tests for critical bug-fix code, CI is failing, and the //todo:dhavkuma markers indicate unfinished state. Address the Important items and get CI green.
Note: CI checks are currently failing - this should be resolved before merge.
Next Steps
- Remove all four
//todo:dhavkumacomments. - Add unit tests for the new helpers and the updated integration points.
- Resolve the duplicate-PR situation with PR #2500.
Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 0m 59s | Cost: $2.41 | Commit: 91ddad8c02109744619cddec5b19432ee3d2c783
If this code review was useful, please react with 👍. Otherwise, react with 👎.
…subpath sites - prerender: getTopAgenticUrls now applies isUrlUnderSiteBase() filter so domain-wide Athena results are scoped to the site's base URL path (e.g. nba.com/timberwolves). Organic top-page URLs already had this filter. - sitemap: skip audit and return a no-op result for subpath sites - robots.txt and sitemap.xml are root-domain resources the subpath site owner cannot control. - Removed three todo markers; all were already using site.getBaseURL() correctly. JIRA: LLMO-4494 LLMO-4495 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This PR will trigger a minor release when merged. |
…-wide suggestion Adds a test verifying that prepareDomainWideAggregateSuggestion scopes allowedRegexPatterns and pathPattern to the site's URL subpath when the baseUrl has a non-root pathname (e.g. /timberwolves → '/timberwolves/*'). Also validates the pattern works as a regex against both url.pathname (CDN edge check in tokowaka-worker) and full URL strings (tokowaka-client coverage check). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
changes scoped with prerender moved to #2605 |
Problem
For subpath sites (e.g.
nba.com/kingsregistered as its own site object), the prerender audit had two issues:Critical — wrong CDN rule scope:
allowedRegexPatternsandpathPatternin the domain-wide suggestion were hardcoded to'/*'. When a customer deploys the domain-wide suggestion fornba.com/kings, the CDN prerender rule would apply to all of nba.com, not just/kings/*.Safety — organic URL bleed:
SiteTopPage.allBySiteIdAndSourceAndGeois scoped bysiteId, but GSC can return domain-wide data. Top-page URLs not belonging to the subpath would get submitted for scraping under the wrong site.Changes
src/prerender/handler.jsgetSitePathPattern(baseUrl)— new helper that derives the correct glob pattern from the site's base URL pathname:https://nba.com→'/*'https://nba.com/kings→'/kings/*'isUrlUnderSiteBase(url, baseUrl)— new helper that returnstruewhen a URL falls within the site's registered path; no-op for root sites.prepareDomainWideAggregateSuggestion— usesgetSitePathPattern(baseUrl)for bothallowedRegexPatternsandpathPatterninstead of hardcoded'/*'.getDomainWideSuggestionUrl— labels subpath sites as'All Subpath URLs'instead of'All Domain URLs'.getTopOrganicUrlsFromSeo— filters top-page URLs throughisUrlUnderSiteBasebefore returning.What was already working
buildSiteFiltersincdn-utils.jsalready generates aREGEXP_LIKESQL clause scoped to the site's pathname — no change needed.Opportunity,Suggestion,PageCitability): already scoped bysiteId, which is unique per subpath site.toPathnamekeying works correctly with subpath pathnames.siteId, naturally isolated per site.Testing
getSitePathPatternandisUrlUnderSiteBaseprepareDomainWideAggregateSuggestionwith a subpathbaseUrlnba.com/kingshaspathPattern: '/kings/*'nba.comstill getspathPattern: '/*'🤖 Generated with Claude Code