Skip to content

feat(llmo-3354): add PATCH endpoint to clear edge status on 404 pages#2174

Draft
anagarwa wants to merge 1 commit intomainfrom
feat/llmo-3354-page-citability-404-clear
Draft

feat(llmo-3354): add PATCH endpoint to clear edge status on 404 pages#2174
anagarwa wants to merge 1 commit intomainfrom
feat/llmo-3354-page-citability-404-clear

Conversation

@anagarwa
Copy link
Copy Markdown
Contributor

Summary

  • Adds PATCH /sites/:siteId/page-citability/status endpoint
  • When called with a URL that returned HTTP 404, clears isDeployedAtEdge = false and resets citabilityScore = 0 for the corresponding PageCitability record
  • If the page isn't found in PageCitability (never tracked), returns { updated: false } with no error
  • If httpStatus is not 404, returns { updated: false } (no-op for non-404 statuses)
  • Route is protected by site:write capability

Use Case

The edge worker observes when a previously-deployed page starts returning 404 (page deleted/moved). This endpoint lets the worker notify SpaceCat so the citability data remains accurate and the page is not shown as edge-deployed.

Test plan

  • All 233 unit tests pass
  • PATCH /sites/:siteId/page-citability/status with { url: "...", httpStatus: 404 } sets isDeployedAtEdge=false and citabilityScore=0 on the record
  • Same request for a URL not in PageCitability returns { updated: false } with 200
  • Request with httpStatus: 200 returns { updated: false } without touching the record

Fixes LLMO-3354

🤖 Generated with Claude Code

Adds POST /sites/:siteId/page-citability/status endpoint that,
when called with a URL returning 404, clears the edgeDeployed flag
and resets citabilityScore to 0 for that page's citability record.

This allows the edge worker to notify SpaceCat when a page that was
previously deployed to the edge returns a 404 (e.g. page was deleted),
so the citability data stays accurate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 10, 2026 07:52
@github-actions
Copy link
Copy Markdown

This PR will trigger a minor release when merged.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new site-scoped API endpoint intended for an edge worker to notify SpaceCat when a previously deployed page starts returning 404, so the corresponding PageCitability state can be cleared.

Changes:

  • Added PATCH /sites/:siteId/page-citability/status route + required capability (site:write).
  • Implemented SitesController.patchPageCitabilityStatus to clear isDeployedAtEdge and reset citabilityScore when httpStatus === 404.
  • Updated SitesController unit test “exported functions” whitelist to include the new handler.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/controllers/sites.js Implements the new PATCH handler that updates PageCitability on 404.
src/routes/index.js Registers the new PATCH route to the SitesController handler.
src/routes/required-capabilities.js Protects the new route with site:write.
test/controllers/sites.test.js Adds the new controller function to the expected exported functions list.

Comment thread src/routes/index.js
Comment on lines 340 to 344
'GET /sites/:siteId/brand-profile': sitesController.getBrandProfile,
'POST /sites/:siteId/brand-profile': sitesController.triggerBrandProfile,
'GET /sites/:siteId/page-citability/counts': sitesController.getPageCitabilityCounts,
'PATCH /sites/:siteId/page-citability/status': sitesController.patchPageCitabilityStatus,
'GET /sites/:siteId/top-pages': sitesController.getTopPages,
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new public HTTP endpoint was added to the router, but the OpenAPI specs under docs/openapi/ don't appear to be updated in this PR. Please add this route (and its request/response schema) to the OpenAPI entrypoint (e.g., docs/openapi/api.yaml plus a referenced path section), so generated docs stay accurate.

Copilot uses AI. Check for mistakes.
Comment thread src/controllers/sites.js
const patchPageCitabilityStatus = async (context) => {
const { siteId } = context.params;
const { url, httpStatus } = context.data || {};

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

patchPageCitabilityStatus updates site-scoped data but does not validate siteId, load the Site, or enforce accessControlUtil.hasAccess(site) (unlike other /sites/:siteId/* handlers in this controller). Without this, callers with the route capability may be able to clear records for sites they don’t belong to. Add the standard siteId validation + Site.findById + org access check before any update logic.

Suggested change
if (!isValidUUID(siteId)) {
return badRequest('Site ID required');
}
const site = await Site.findById(siteId);
if (!site) {
return notFound('Site not found');
}
if (!await accessControlUtil.hasAccess(site)) {
return forbidden('Only users belonging to the organization can update page citability status');
}

Copilot uses AI. Check for mistakes.
Comment thread src/controllers/sites.js
Comment on lines +1318 to +1322
const { PageCitability } = dataAccess;
const record = await PageCitability.findByUrl(url);
if (!record) {
return ok({ url, httpStatus, updated: false });
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route is parameterized by :siteId, but the update is driven by PageCitability.findByUrl(url) with no verification the returned record belongs to that site. This can cause cross-site updates if the same URL can exist under different sites (or if a caller supplies a URL for a different site). Prefer a site-scoped lookup (e.g., findBySiteIdAndUrl(siteId, url)) or validate record.getSiteId() === siteId before mutating/saving.

Copilot uses AI. Check for mistakes.
Comment on lines 133 to 137
'updateSite',
'updateCdnLogsConfig',
'getPageCitabilityCounts',
'patchPageCitabilityStatus',
'getTopPages',
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new mutating endpoint is introduced, but there are no unit tests covering patchPageCitabilityStatus behavior (404 clears fields, non-404 no-op, unknown URL returns updated:false, missing url -> 400, and access denied). Please add controller tests similar to existing SitesController tests; this change currently only updates the exported-function whitelist.

Copilot generated this review using guidance from repository custom instructions.
@anagarwa anagarwa marked this pull request as draft April 10, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants