Skip to content

fix(LLMO-4176): skip brandalf check when onboardingMode is v1 in llmo-customer-analysis#2380

Merged
irenelagno merged 4 commits intomainfrom
fix/llmo-4176-v1-onboarding-skip-brandalf-check
Apr 15, 2026
Merged

fix(LLMO-4176): skip brandalf check when onboardingMode is v1 in llmo-customer-analysis#2380
irenelagno merged 4 commits intomainfrom
fix/llmo-4176-v1-onboarding-skip-brandalf-check

Conversation

@irenelagno
Copy link
Copy Markdown
Contributor

Summary

  • Root cause: For mixed-state orgs (brandalf=true feature flag but pre-Brandalf sites that force v1 onboarding via hasPreBrandalfSites), the llmo-customer-analysis handler was calling isBrandalfEnabled independently of the actual onboarding path. It found no v2 customer config brand (none created during v1 onboarding) and called DRS without brand_id. DRS rejects this with 422 - brand_id is required for v2 (brandalf-enabled) sites.
  • Fix: Short-circuit isBrandalfEnabled when auditContext.onboardingMode === 'v1'. The onboardingMode is set by spacecat-api-service based on resolveLlmoOnboardingMode and propagated through drs-prompt-generationllmo-customer-analysis. When it's explicitly 'v1', we skip v2 brand resolution and create the BP schedule without brand_id.
  • Test: New unit test covers the mixed-state scenario, asserting the feature-flags API is never called and the schedule payload omits brand_id/spacecat_org_id.

Behaviour

onboardingMode brandalf flag Outcome
'v2' true Resolve brand from DB, include brand_id in schedule
'v1' (explicit) true Skip brandalf check, create schedule without brand_id
not set true Fall back to isBrandalfEnabled (backward compat)
not set false No brand resolution, schedule without brand_id

Related

Test plan

  • Unit tests pass (npm test)
  • Deploy to dev and re-run v1 onboarding for nordstrom.com (site 4483e763-a918-431d-8b7a-ec8d4f3bf9d9) — confirm brand-presence schedule created successfully in CloudWatch logs

🤖 Generated with Claude Code

…-customer-analysis

For mixed-state orgs (brandalf=true flag but pre-Brandalf sites forcing v1
onboarding), the llmo-customer-analysis handler was checking isBrandalfEnabled
and finding no v2 brand (none created in v1 path), then calling DRS without
brand_id. DRS rejects this with 422 for brandalf-enabled orgs.

Fix: short-circuit isBrandalfEnabled when auditContext.onboardingMode === 'v1'
so the BP schedule is created without brand_id, matching v1 DRS expectations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@irenelagno
Copy link
Copy Markdown
Contributor Author

Related PRs

api-service safeguard (pairs with this fix):
adobe/spacecat-api-service#2171

Why both PRs are needed

PR Repo What it does
#2171 spacecat-api-service Adds resolveLlmoOnboardingMode safeguard — forces v1 for orgs with pre-Brandalf sites even when brandalf=true flag is set
This PR (#2380) spacecat-audit-worker Fixes llmo-customer-analysis to respect onboardingMode='v1' from auditContext instead of re-checking isBrandalfEnabled independently

Without the api-service fix, mixed-state orgs would be onboarded as v2 (wrong). Without this fix, those orgs would fail brand-presence schedule creation with DRS 422.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

This PR will trigger a patch release when merged.

irenelagno and others added 2 commits April 14, 2026 13:20
When resolving which brand to use for the brand presence schedule, prefer
the brand whose baseSiteId (site_id column) matches the site over a
brand_sites join match. The onboarding-created brand has the correct base
URL, but Brandalf-created sub-brands may have sub-path URLs that fail
DRS URL validation (422).

Falls back to brand_sites match for backward compatibility with brands
created before baseSiteId was set during onboarding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
irenelagno added a commit to adobe/spacecat-api-service that referenced this pull request Apr 15, 2026
…boarding mode resolution (#2171)

## Summary

Implements [LLMO-4176](https://jira.corp.adobe.com/browse/LLMO-4176)
(epic [LLMO-4054](https://jira.corp.adobe.com/browse/LLMO-4054)).

Rewrites `resolveLlmoOnboardingMode` to follow an 8-row decision matrix
based on 3 inputs:

| # | Default version | Pre-cutoff sites | Brandalf flag | Onboarding
version | Side effects |
|---|---|---|---|---|---|
| 1 | v1 | yes | yes | v1 | Reverts brandalf to false + logs warning |
| 2 | v1 | yes | no | v1 | — |
| 3 | v1 | no | yes | v2 | — |
| 4 | v1 | no | no | v1 | — |
| 5 | v2 | yes | yes | v2 | — |
| 6 | v2 | yes | no | v1 | — |
| 7 | v2 | no | yes | v2 | — |
| 8 | v2 | no | no | v2 | Sets brandalf to true |

**Priority order:** Brandalf flag (highest) → kill switch → legacy site
check → default v2.

**Temporary safeguard** — will be removed once all v1 customers are
migrated to v2.

## Related PRs

> **⚠️ Both PRs must be merged and deployed together.**

| PR | Repo | What |
|---|---|---|
| **This PR (#2171)** | spacecat-api-service | Decision matrix + DRS
baseUrl fix |
|
[adobe/spacecat-audit-worker#2380](adobe/spacecat-audit-worker#2380)
| spacecat-audit-worker | Fixes brand resolution to prefer `baseSiteId`
over `brand_sites` join |

### What changed

**`src/support/llmo-onboarding-mode.js`** — Rewrites
`resolveLlmoOnboardingMode` with 4-step logic:
1. Read brandalf flag — if `true`: check for Row 1 condition (kill
switch + pre-cutoff → revert flag to false, return v1), otherwise return
v2
2. If brandalf false/missing + kill switch
`LLMO_ONBOARDING_DEFAULT_VERSION=v1` → v1
3. Legacy check: org has pre-cutoff sites → v1
4. Default → v2

New exports (all TEMPORARY):
- `LLMO_BRANDALF_GA_CUTOFF_MS_DEFAULT` — epoch-ms constant
(`2026-04-01T00:00:00Z`)
- `resolveBrandalfCutoffMs(context)` — reads cutoff from
`LLMO_BRANDALF_GA_CUTOFF_MS` env var
- `hasPreBrandalfSites(organizationId, context)` — returns `true` if org
has any site created before cutoff

**`src/controllers/llmo/llmo-onboarding.js`** — Fixes DRS baseUrl bug
(NASCAR issue): passes `overrideBaseURL` to DRS prompt generation job
when available.

### Files changed

| File | What |
|---|---|
| `src/support/llmo-onboarding-mode.js` | Decision matrix logic + Row 1
revert |
| `src/controllers/llmo/llmo-onboarding.js` | DRS baseUrl fix
(`overrideBaseURL`) |
| `src/support/customer-config-mapper.js` | Minor fix |
| `test/support/llmo-onboarding-mode.test.js` | Rewritten unit tests (45
cases covering all 8 matrix rows) |
| `test/controllers/llmo/llmo-onboarding.test.js` | Updated mocks for
new logic |
| `test/support/slack/actions/onboard-llmo-modal.test.js` | Updated
mocks |
| `test/it/shared/tests/llmo-onboarding.js` | IT tests for
`hasPreBrandalfSites` + `resolveLlmoOnboardingMode` |
| `test/it/postgres/llmo-onboarding.test.js` | Wire PostgREST client
into IT tests |
| `test/it/postgres/seed-data/organizations.js` | Add legacy + new LLMO
test orgs |
| `test/it/postgres/seed-data/sites.js` | Add sites with explicit
`created_at` |
| `test/it/shared/seed-ids.js` | Add IDs for new test orgs/sites |
| `docs/llmo-brandalf-apis/v1-v2-onboarding-consistency-safeguard.md` |
Design doc with decision matrix |

## Test plan

### Unit tests (automated — run in CI)

```bash
npx mocha test/support/llmo-onboarding-mode.test.js
# 45 tests — all 8 matrix rows, edge cases, error handling

npx mocha test/controllers/llmo/llmo-onboarding.test.js
# 79 tests — full performLlmoOnboarding suite
```

### Integration tests (automated — require Docker)

```bash
npx mocha --require test/it/postgres/harness.js --timeout 30000 \
  test/it/postgres/llmo-onboarding.test.js
```

Covers:
- `hasPreBrandalfSites` → `true` for org with pre-cutoff site
- `hasPreBrandalfSites` → `false` for org with post-cutoff site
- `hasPreBrandalfSites` → `false` for org with no sites
- `resolveLlmoOnboardingMode` → `v1` for legacy org
- `resolveLlmoOnboardingMode` → `v2` for new org
- `resolveLlmoOnboardingMode` → `v1` when kill switch active

### E2E validation (manual — completed on dev)

Validated on dev environment (`spacecat.experiencecloud.live/api/ci`)
with two test orgs. Results documented in
`docs/llmo-brandalf-apis/e2e-test-results.md`.

| Test | Row | Result |
|------|-----|--------|
| Row 7: default=v2, no pre-cutoff, brandalf=true → v2 | PASS |
| Row 8: default=v2, no pre-cutoff, no brandalf → v2 + sets flag | PASS
|
| Row 5: default=v2, pre-cutoff, brandalf=true → v2 | PASS |
| Row 6: default=v2, pre-cutoff, no brandalf → v1 | PASS |

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@irenelagno irenelagno merged commit 86e396a into main Apr 15, 2026
18 checks passed
@irenelagno irenelagno deleted the fix/llmo-4176-v1-onboarding-skip-brandalf-check branch April 15, 2026 15:56
solaris007 pushed a commit that referenced this pull request Apr 15, 2026
## [1.415.1](v1.415.0...v1.415.1) (2026-04-15)

### Bug Fixes

* **LLMO-4176:** skip brandalf check when onboardingMode is v1 in llmo-customer-analysis ([#2380](#2380)) ([86e396a](86e396a))
@solaris007
Copy link
Copy Markdown
Member

🎉 This PR is included in version 1.415.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants