Skip to content

feat: add includedURLs support to patchAuditForSite endpoint#2355

Open
noruiz wants to merge 13 commits into
mainfrom
fix/LLMO-4070-audit-included-urls
Open

feat: add includedURLs support to patchAuditForSite endpoint#2355
noruiz wants to merge 13 commits into
mainfrom
fix/LLMO-4070-audit-included-urls

Conversation

@noruiz
Copy link
Copy Markdown
Contributor

@noruiz noruiz commented May 6, 2026

Summary

Fixes LLMO-4070 (backend portion)

What changed

  • Extended PATCH /sites/:siteId/:auditType to accept includedURLs (array of URLs) with merge/replace semantics via replaceIncludedURLs boolean flag
  • Added replaceExcludedURLs flag to give callers atomic control over excludedURLs
  • Added includedURLs and both replace flags to the UpdateHandlerTypeConfig and HandlerConfig OpenAPI schemas
  • 12 new test cases covering validation, clear/merge/replace modes, deduplication, combined requests, and the undefined-handlers edge case

Why

The config.handlers[auditType].includedURLs field existed in the data model but had no API surface. The Config model (external package) has no updateIncludedURLs setter, so includedURLs is applied by patching the plain object returned by Config.toDynamoItem() directly before site.setConfig().

Assumptions made

  • Config.toDynamoItem() returns handlers as the same object reference as state.handlers, making the configObj patch equivalent to a state mutation in the normal case
  • In production, state.handlers is always initialized to {} by schema default — the undefined-handlers path is an edge case

Testing

Unit tests cover: non-array input, invalid URL validation, empty-array clear, merge with no existing, merge with existing, deduplication, atomic replace, replaceExcludedURLs: false merge regression, combined includedURLs+excludedURLs request, undefined-handlers persistence, response body correctness

Code review

This solution went through 3 automated subagent review iterations.

  • Iteration 1 (sonnet): null guard, missing test for undefined handlers, format:uri in schema — resolved
  • Iteration 2 (opus): silent write-loss root cause fix, false-positive tests — resolved
  • Iteration 3 (sonnet): format:uri consistency, misleading test name, simplified response, combined-fields test — resolved

Extend the PATCH /sites/:siteId/:auditType endpoint to accept and
persist includedURLs per audit handler, with merge/replace semantics
controlled by replaceIncludedURLs and replaceExcludedURLs flags.

The Config model (external package) has no updateIncludedURLs setter,
so includedURLs is applied by patching the configObj returned by
Config.toDynamoItem() before calling site.setConfig(). This correctly
handles the edge case where getHandlers() returns undefined.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

This PR will trigger a minor release when merged.

@noruiz noruiz self-assigned this May 7, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@noruiz noruiz temporarily deployed to dev-branches May 7, 2026 19:58 — with GitHub Actions Inactive
@noruiz noruiz marked this pull request as ready for review May 8, 2026 15:33
@noruiz noruiz changed the title feat(LLMO-4070): add includedURLs support to patchAuditForSite endpoint feat: add includedURLs support to patchAuditForSite endpoint May 8, 2026
noelruiz34 and others added 9 commits May 8, 2026 11:30
…fix test organisation

- Shallow-copy configObj.handlers and configObj.handlers[auditType] before
  assigning includedURLs to avoid mutating live Config state through the
  shared reference returned by toDynamoItem
- Update unit tests to assert via site.setConfig args instead of the now-
  isolated handler object (tests were previously passing only due to the
  shared-reference mutation that the fix removes)
- Add integration tests for PATCH /sites/:siteId/:auditType includedURLs
  merge, replace, clear, persist round-trip, validation, and access control
- Move replaceExcludedURLs unit tests into their own describe block
- Add replaceIncludedURLs/replaceExcludedURLs to UpdateHandlerTypeConfig
  OpenAPI example

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
context.data can be null/undefined with malformed requests before body
parsing completes; destructuring it directly throws a 500 instead of
returning a 400. Adding ?? {} makes the destructure safe.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…URLs write path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…:auditType 500s

Configuration is read from S3 (not PostgREST), so the dummy-config-bucket
was missing in MinIO, causing Configuration.findLatest() to throw on every
PATCH request and surface as a 500 in IT tests. Seed a minimal config with
all known handlers on harness startup.

Also adds the context.data null branch test for patchAuditForSite (100%
branch coverage on audits.js).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Configuration.findLatest() returns null when no config exists in S3
(NoSuchKey case). Calling .getHandlers() on null threw a TypeError,
surfacing as a 500 in environments where the config bucket exists but
has no object (IT test VPC environment). Skip the audit-type validation
when no configuration is available — in production the config is always
present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…orSite

findLatest throws (not returns null) when S3 throws NoSuchBucket or
AccessDenied. Wrap in try-catch so unavailable configuration skips the
audit-type check instead of surfacing a 500.
@noruiz noruiz force-pushed the fix/LLMO-4070-audit-included-urls branch from d60096c to d156595 Compare May 11, 2026 18:41
@noruiz noruiz temporarily deployed to dev-branches May 11, 2026 18:53 — with GitHub Actions Inactive
Comment thread src/controllers/audits.js Outdated
Bare catch {} swallowed all errors silently. Log the error at warn level
so S3 unavailability is visible in logs while still allowing the request
to proceed without the audit-type registration check.
@noruiz noruiz requested a review from baranovskyalexandr May 11, 2026 21:12
@noruiz noruiz temporarily deployed to dev-branches May 11, 2026 21:21 — with GitHub Actions Inactive
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.

3 participants