fix(onboard-status): report audit/scrape state truthfully during onboarding - #340
Conversation
…arding The onboarding status report conflated "still running" with "failed", so a status snapshot taken mid-onboarding wrongly showed most audits as having failed for the site. Root causes and fixes: - Audit run-status was derived by grepping CloudWatch audit-worker logs for a "Received <audit> audit request" line. Within the onboard wait window that line often hadn't landed yet, yielding a false "<audit> audit has not been executed". Replace this with the DB Audit records already loaded for the completion check (computeAuditCompletion): an audit that has not completed is reported as in progress (⏳), never as "not executed". Removes the fragile/slow CloudWatch dependency entirely (deletes cloudwatch-utils.js + its test and obsolete CloudWatch tests). - Scraping availability was binary (completedCount > 0 ? ✅ : ❌), so a scrape still in progress (0 complete, many URLs PENDING/RUNNING) showed as failed. Add a tri-state deriveScrapingStatus (available/in_progress/ failed/unknown) rendered as ✅/⏳/❌, and surface an "In progress: N" count in the scraping stats message. - security-vulnerabilities only runs for AEM_CS delivery type, so on aem_edge/other sites it can never produce an opportunity yet was reported as missing/failed. Add isOpportunityApplicableForDeliveryType and filter expectedOpportunityTypes by the site's delivery type. analyzeMissingOpportunities is now a pure function (DB-driven, no I/O) and is unit-tested directly, along with deriveScrapingStatus and the delivery-type predicate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…e audits Adds a handler-level test for a completed audit that produced no opportunity (rendered with ℹ️ in the Audit Processing Errors section), closing the codecov/patch gap on handler.js. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
This PR will trigger a patch release when merged. |
…fix/onboard-status-truthful-reporting
tathagat2241
left a comment
There was a problem hiding this comment.
Review: fix(onboard-status): report audit/scrape state truthfully during onboarding
Bugfix (+437/−1006; net simplification, mostly dead CloudWatch removal). Fixes the "still running" vs "failed" conflation in the onboard status report across three surfaces: audit run-status (now DB-driven, not CloudWatch log-grepping), scraping (binary → tri-state), and delivery-type-aware opportunity expectations. I focused on the one place this could go subtly wrong — the delivery-type casing — and verified it against the authoritative enum.
Blockers
- None.
Should-fix
- None.
Nits / things to confirm
- True audit-level failures now read as "in progress" (⏳), not "failed." Removing the CloudWatch path also removed the only audit-crash failure signal — a genuinely failed audit that wrote no completion record now shows as in-progress within the onboard window (dependency failures are still surfaced as ❌). This is a deliberate, sound tradeoff (eliminating false failures during a bounded, snapshot-then-follow-up flow), but worth a PM nod that a crashed audit is no longer distinctly flagged by this processor.
deriveScrapingStatustreats any non-{COMPLETE, PENDING, RUNNING}URL status as failed (when nothing has completed): a scrape-URL in some other non-terminal state (e.g.QUEUED/PROCESSING, if those exist) would read asfailedrather than in-progress, andunknown(total 0) renders as ❌. Worth confirming the scrape-URL status enum is exactly those four; otherwise widen thependingpredicate.- Rare label inconsistency: if an audit is
completedbut scraping still shows 0-completed, the top-line scraping shows ⏳ (tri-state) while the missing-opportunity analysis still evaluatesserviceStatus.scrapingas an unavailable dependency (binary ❌). Very low likelihood (audits need scraping first), just noting the two surfaces can disagree in that narrow ordering.
Strengths
- Delivery-type filter casing is correct — verified against the source of truth.
DELIVERY_TYPES.AEM_CS === 'aem_cs'(lowercase) inspacecat-shared-utils, and the audit-worker gates on exactlysite.getDeliveryType() !== DELIVERY_TYPES.AEM_CS, so the PR's lowercase{'security-vulnerabilities': ['aem_cs']}matches — it keeps the opportunity on AEM CS sites and drops it elsewhere, as intended. The map is conservatively scoped to the one known hard gate, avoiding hiding legitimately-producible opportunities, with a comment pointing at the audit-worker source. analyzeMissingOpportunitiesis now a pure, DB-driven function (no CloudWatch I/O), unit-tested directly.computeAuditCompletionis computed once and itscompleted/pendingsplit is reused as the single source for both the in-progress (⏳) opportunity statuses and the missing-opportunity analysis — and the!completed.has(auditType)in-progress check correctly short-circuits before the dependency check, so an in-flight audit reads as ⏳ rather than a dependency failure.- Removes a fragile, slow path (CloudWatch log-grepping for
Received <audit> audit request, which routinely hadn't landed within the wait window) and ~1000 lines of dead code/tests with it. - Conservative DB-error fallback — on an
Audit.allLatestForSitefailure, everything is marked pending so nothing is misreported as failed/executed and the "may still be in progress" disclaimer shows. - Good targeted tests — one unit test file per new pure function (
analyze-missing-opportunities,derive-scraping-status,delivery-type-applicability) plus a delivery-type integration test.
Tests
Strong for the changed surfaces — the three new pure functions are tested directly and the delivery-type unit test uses lowercase inputs matching the verified enum. I could not execute the suite here, so 414 passing / 0 failing is trusted rather than confirmed.
Verdict
Approve. Correctly fixes the running-vs-failed conflation on all three surfaces, with the delivery-type casing verified safe against the authoritative DELIVERY_TYPES enum and the audit-worker's own gate, plus a healthy dead-code removal and direct unit tests. The nits are minor (an intended failure-reporting tradeoff and two edge-case labelings), none blocking.
…dicate Addresses review nit: document that PENDING/RUNNING are the only non-terminal scrape_url_status values (enum: PENDING, RUNNING, REDIRECT, COMPLETE, FAILED, STOPPED), so the in-progress predicate is provably complete and REDIRECT/FAILED/ STOPPED correctly read as failed when nothing has completed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the thorough review 🙏 — responses to the three nits: 1. Crashed audits now read as ⏳ instead of a distinct failure. Confirmed intentional. This is the deliberate tradeoff: a hard-crashed audit writes no 2. 3. Tri-state (⏳) vs binary dependency (❌) label disagreement. Acknowledged as a known, near-impossible edge: the missing-opportunity analysis only reaches the |
## [1.16.4](v1.16.3...v1.16.4) (2026-08-03) ### Bug Fixes * **onboard-status:** report audit/scrape state truthfully during onboarding ([#340](#340)) ([1d839a9](1d839a9))
|
🎉 This PR is included in version 1.16.4 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
…ot failed (#343) Follow-up to #340 (merged): the onboarding status report mapped the 'unknown' scraping state (no scrape data yet) to ❌, which reads as a failure on an early snapshot of a not-yet-scraped site — the running-vs-failed conflation #340 set out to remove. Map 'unknown' to a neutral info icon (ℹ️): not ❌ (false failure) and not ⏳ (overclaims active progress). A genuinely terminal-failed scrape (0 completed, 0 pending, >0 failed) still resolves to ❌ via the tri-state. Mirrors the same fix in spacecat-api-service's onboard-status command, keeping the two deriveScrapingStatus consumers in sync. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Problem
During site onboarding, the
opportunity-status-processorstatus report conflated "still running" with "failed". A snapshot taken mid-onboarding wrongly showed most audits as having failed — e.g.Scraping ❌and<audit> audit has not been executed— when the pipeline was simply still in flight. A follow-uponboard statusthen reported everything complete, but the initial message had already caused confusion.Root causes & fixes
1. Audit run-status from the DB, not CloudWatch logs
Execution was inferred by grepping the audit-worker CloudWatch log group for a
Received <audit> audit requestline. Within the onboard wait window that line frequently hadn't landed yet, producing a false<audit> audit has not been executed. This now uses theAuditDB records already loaded for the completion check (computeAuditCompletion): an audit that hasn't completed is reported as in progress (⏳), never as "not executed". The fragile/slow CloudWatch path is removed entirely (cloudwatch-utils.js+ its test and obsolete CloudWatch test blocks deleted).analyzeMissingOpportunitiesis now a pure function (DB-driven, no I/O) and unit-tested directly.2. Scraping tri-state
scrapingAvailablewas binary (completedCount > 0 ? white_check_mark : x), so a scrape still running (0 complete, many URLsPENDING/RUNNING) showed as failed. NewderiveScrapingStatusreturnsavailable/in_progress/failed/unknown, rendered as ✅ / ⏳ / ❌. The stats message also surfaces anIn progress: Ncount (explains snapshots wheretotalfar exceedscompleted + failed).3. Delivery-type-aware expectations
security-vulnerabilitiesonly runs forAEM_CSdelivery type, so onaem_edge/other sites it can never produce an opportunity, yet was reported as missing/failed. NewisOpportunityApplicableForDeliveryTypefiltersexpectedOpportunityTypesby the site's delivery type.Tests
analyze-missing-opportunities,derive-scraping-status,delivery-type-applicability, plus a delivery-type integration test.npm testcoverage gate passes; lint clean.🤖 Generated with Claude Code