Skip to content

Commit 977e4e9

Browse files
irenelagnoclaude
andauthored
feat(LLMO-4176): add brandalf flag override and decision matrix to onboarding 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>
1 parent a38e591 commit 977e4e9

16 files changed

Lines changed: 1577 additions & 210 deletions

docs/llmo-brandalf-apis/v1-v2-onboarding-consistency-safeguard.md

Lines changed: 684 additions & 0 deletions
Large diffs are not rendered by default.

src/controllers/llmo/llmo-onboarding.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ export function buildInitialCustomerConfigV2({
215215
brand.baseUrl = primaryUrl;
216216
brand.updatedAt = timestamp;
217217
brand.updatedBy = updatedBy;
218-
brand.urls = [{ value: primaryUrl, type: 'url' }];
218+
brand.urls = [{ value: primaryUrl, type: 'base' }];
219219
brand.brandAliases = [{ name: brandName, regions: ['gl'] }];
220220

221221
config.customer.customerName = brandName;
@@ -275,7 +275,7 @@ export async function ensureInitialCustomerConfigV2({
275275
regions: ['gl'],
276276
updatedAt: timestamp,
277277
updatedBy: resolveUpdatedBy(context),
278-
urls: [{ value: primaryUrl, type: 'url' }],
278+
urls: [{ value: primaryUrl, type: 'base' }],
279279
brandAliases: [{ name: trimmedName, regions: ['gl'] }],
280280
});
281281

@@ -1013,6 +1013,12 @@ export async function createOrFindSite(baseURL, organizationId, context, deliver
10131013
if (site) {
10141014
if (site.getOrganizationId() !== organizationId) {
10151015
site.setOrganizationId(organizationId);
1016+
// Persist the re-parent immediately. resolveLlmoOnboardingMode (called
1017+
// right after this in performLlmoOnboarding) reads sites by org_id, so
1018+
// the move must be visible to that query — otherwise a legacy site
1019+
// re-parented into a brand-new org would be classified as v2 and create
1020+
// an instant mixed v1/v2 state. (LLMO-4176)
1021+
await site.save();
10161022
}
10171023

10181024
return site;
@@ -1259,11 +1265,17 @@ export async function performLlmoOnboarding(params, context, say = () => {}) {
12591265

12601266
// Create or find organization
12611267
const organization = await createOrFindOrganization(imsOrgId, context, say);
1262-
const onboardingMode = await resolveLlmoOnboardingMode(organization.getId(), context);
12631268

1264-
// Create site
1269+
// Create site BEFORE resolving the onboarding mode. createOrFindSite may
1270+
// re-parent an existing site into the destination org; resolveLlmoOnboardingMode
1271+
// reads Site.allByOrganizationId, so the re-parent has to be persisted first
1272+
// (createOrFindSite saves the site in that branch). Otherwise a legacy
1273+
// pre-cutoff site moved into a brand-new org would be misclassified as v2
1274+
// and instantly create the mixed state LLMO-4176 was filed to prevent.
12651275
site = await createOrFindSite(baseURL, organization.getId(), context, deliveryType);
12661276

1277+
const onboardingMode = await resolveLlmoOnboardingMode(organization.getId(), context);
1278+
12671279
log.info(`Created site ${site.getId()} for ${baseURL} using LLMO onboarding mode ${onboardingMode}`);
12681280

12691281
// Create entitlement and enrollment
@@ -1363,7 +1375,7 @@ export async function performLlmoOnboarding(params, context, say = () => {}) {
13631375
name: brandName.trim(),
13641376
status: 'active',
13651377
baseSiteId: site.getId(),
1366-
urls: [{ value: baseURL, type: 'url' }],
1378+
urls: [{ value: baseURL, type: 'base' }],
13671379
brandAliases: [{ name: brandName.trim(), regions: ['gl'] }],
13681380
},
13691381
postgrestClient,
@@ -1417,7 +1429,7 @@ export async function performLlmoOnboarding(params, context, say = () => {}) {
14171429

14181430
const drsJob = await submitOnboardingPromptGenerationJob({
14191431
drsClient,
1420-
baseUrl: baseURL,
1432+
baseUrl: siteConfig.getFetchConfig?.()?.overrideBaseURL || baseURL,
14211433
brandName: brandName.trim(),
14221434
audience,
14231435
region: 'US',

src/support/customer-config-mapper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export function convertV1ToV2(llmoConfig, brandName, imsOrgId) {
134134
});
135135

136136
const brandRegions = allRegions.size > 0 ? Array.from(allRegions) : ['gl'];
137-
const brandUrls = Array.from(allUrls).map((url) => ({ value: url, type: 'url' }));
137+
const brandUrls = Array.from(allUrls).map((url) => ({ value: url, type: 'base' }));
138138

139139
// Only create a brand if we have brand aliases
140140
if (brandAliases.length === 0) {

src/support/llmo-onboarding-mode.js

Lines changed: 159 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import { readFeatureFlag } from './feature-flags-storage.js';
13+
import { readFeatureFlag, upsertFeatureFlag } from './feature-flags-storage.js';
1414

1515
export const LLMO_FEATURE_FLAG_PRODUCT = 'LLMO';
1616
export const LLMO_BRANDALF_FLAG = 'brandalf';
1717
export const LLMO_ONBOARDING_MODE_V1 = 'v1';
1818
export const LLMO_ONBOARDING_MODE_V2 = 'v2';
1919

20-
export function normalizeLlmoOnboardingMode(mode) {
21-
return mode === LLMO_ONBOARDING_MODE_V2 ? LLMO_ONBOARDING_MODE_V2 : LLMO_ONBOARDING_MODE_V1;
22-
}
20+
/**
21+
* Brandalf GA cutoff in Unix epoch milliseconds (2026-04-01T00:00:00Z).
22+
* Any site whose createdAt is strictly before this value is treated as v1 (legacy).
23+
* Override per-environment via LLMO_BRANDALF_GA_CUTOFF_MS without a full redeploy.
24+
*
25+
* TEMPORARY — remove once all v1 customers have been migrated to v2.
26+
*/
27+
export const LLMO_BRANDALF_GA_CUTOFF_MS_DEFAULT = Date.UTC(2026, 3, 1);
2328

2429
export async function readBrandalfFlagOverride(organizationId, postgrestClient) {
2530
if (!organizationId || !postgrestClient?.from) {
@@ -34,31 +39,170 @@ export async function readBrandalfFlagOverride(organizationId, postgrestClient)
3439
});
3540
}
3641

42+
/**
43+
* Resolves the Brandalf GA cutoff from the environment (epoch ms).
44+
* Falls back to LLMO_BRANDALF_GA_CUTOFF_MS_DEFAULT if the env var is missing or invalid.
45+
*
46+
* TEMPORARY — remove once all v1 customers have been migrated to v2.
47+
*
48+
* @param {object} context - Request context
49+
* @returns {number} Cutoff timestamp in milliseconds
50+
*/
51+
export function resolveBrandalfCutoffMs(context) {
52+
const raw = context?.env?.LLMO_BRANDALF_GA_CUTOFF_MS;
53+
if (raw === undefined || raw === null || raw === '') {
54+
return LLMO_BRANDALF_GA_CUTOFF_MS_DEFAULT;
55+
}
56+
const parsed = Number(raw);
57+
if (!Number.isFinite(parsed) || parsed <= 0) {
58+
context?.log?.warn?.(
59+
`Invalid LLMO_BRANDALF_GA_CUTOFF_MS "${raw}", using default ${LLMO_BRANDALF_GA_CUTOFF_MS_DEFAULT}`,
60+
);
61+
return LLMO_BRANDALF_GA_CUTOFF_MS_DEFAULT;
62+
}
63+
return parsed;
64+
}
65+
66+
/**
67+
* Returns true if the organization has any site whose createdAt is strictly before
68+
* the resolved cutoff. Sites with missing or unparseable createdAt are ignored (not
69+
* treated as legacy) to avoid false positives, but logged so monitoring can pick up
70+
* data-quality issues — silently swallowing them would bias the safeguard toward v2.
71+
*
72+
* TEMPORARY — remove once all v1 customers have been migrated to v2.
73+
*
74+
* @param {string} organizationId
75+
* @param {object} context - Request context (must have context.dataAccess.Site)
76+
* @returns {Promise<boolean>}
77+
*/
78+
export async function hasPreBrandalfSites(organizationId, context) {
79+
const cutoffMs = resolveBrandalfCutoffMs(context);
80+
const { Site } = context.dataAccess;
81+
const log = context?.log;
82+
const sites = await Site.allByOrganizationId(organizationId);
83+
return sites.some((s) => {
84+
const createdAt = s.getCreatedAt?.();
85+
if (createdAt === null || createdAt === undefined) {
86+
log?.warn?.(
87+
`Site ${s.getId?.() ?? '<unknown>'} in org ${organizationId} has no createdAt — skipping legacy check`,
88+
);
89+
return false;
90+
}
91+
const ts = createdAt instanceof Date
92+
? createdAt.getTime()
93+
: new Date(createdAt).getTime();
94+
if (!Number.isFinite(ts)) {
95+
log?.warn?.(
96+
`Site ${s.getId?.() ?? '<unknown>'} in org ${organizationId} has unparseable createdAt "${createdAt}" — skipping legacy check`,
97+
);
98+
return false;
99+
}
100+
return ts < cutoffMs;
101+
});
102+
}
103+
104+
/**
105+
* Resolves the LLMO onboarding mode (v1 or v2) for the given organization.
106+
*
107+
* Decision order (see decision matrix in v1-v2-onboarding-consistency-safeguard.md):
108+
* 1. If brandalf=true on the org:
109+
* a. If kill switch is v1 AND org has pre-cutoff sites → revert brandalf
110+
* flag to false, log warning, return v1 (row 1 remediation).
111+
* b. Otherwise → return v2 (rows 3, 5, 7).
112+
* 2. If LLMO_ONBOARDING_DEFAULT_VERSION is 'v1' → return v1 (kill switch, rows 2, 4).
113+
* 3. If org has pre-cutoff sites → return v1 (legacy protection, row 6).
114+
* 4. Otherwise → return v2 (new customer default, row 8).
115+
*
116+
* TEMPORARY — should be removed once all v1 customers have been migrated to v2.
117+
*
118+
* @param {string} organizationId
119+
* @param {object} context - Request context
120+
* @returns {Promise<'v1'|'v2'>}
121+
*/
37122
export async function resolveLlmoOnboardingMode(organizationId, context) {
38-
const configuredDefault = context?.env?.LLMO_ONBOARDING_DEFAULT_VERSION;
39-
const defaultMode = normalizeLlmoOnboardingMode(configuredDefault);
40123
const { log = console } = context || {};
41124
const postgrestClient = context?.dataAccess?.services?.postgrestClient;
42125

43-
if (configuredDefault && configuredDefault !== defaultMode) {
126+
// 1. Brandalf flag check: if the org has brandalf=true, it has been
127+
// explicitly migrated to v2. Honor it — except when the kill switch
128+
// is active AND the org has pre-cutoff sites (row 1 remediation).
129+
let brandalfEnabled = false;
130+
try {
131+
brandalfEnabled = await readBrandalfFlagOverride(organizationId, postgrestClient) === true;
132+
} catch (flagError) {
44133
log.warn(
45-
`Invalid LLMO_ONBOARDING_DEFAULT_VERSION "${configuredDefault}", falling back to ${defaultMode}`,
134+
`Failed to read brandalf flag for org ${organizationId}: ${flagError.message} — proceeding with default resolution`,
46135
);
47136
}
48137

49-
try {
50-
const override = await readBrandalfFlagOverride(organizationId, postgrestClient);
51-
if (override === true) {
52-
return LLMO_ONBOARDING_MODE_V2;
138+
if (brandalfEnabled) {
139+
const configuredDefault = context?.env?.LLMO_ONBOARDING_DEFAULT_VERSION;
140+
141+
// Row 1: kill switch active + pre-cutoff sites + brandalf=true
142+
// → revert flag to false and force v1.
143+
if (configuredDefault === LLMO_ONBOARDING_MODE_V1) {
144+
try {
145+
if (await hasPreBrandalfSites(organizationId, context)) {
146+
try {
147+
await upsertFeatureFlag({
148+
organizationId,
149+
product: LLMO_FEATURE_FLAG_PRODUCT,
150+
flagName: LLMO_BRANDALF_FLAG,
151+
value: false,
152+
updatedBy: 'llmo-onboarding-mode-resolution',
153+
postgrestClient,
154+
});
155+
log.warn(
156+
`LLMO mode resolution: organization ${organizationId} has brandalf=true but also has `
157+
+ 'pre-cutoff sites while kill switch is active. Reverted brandalf flag to false. '
158+
+ 'This org has sites that require migration before it can use v2.',
159+
);
160+
} catch (revertError) {
161+
log.error(
162+
`Failed to revert brandalf flag for org ${organizationId}: ${revertError.message}. `
163+
+ 'Flag may still be true — manual intervention required.',
164+
);
165+
}
166+
return LLMO_ONBOARDING_MODE_V1;
167+
}
168+
} catch (error) {
169+
log.warn(
170+
`Failed to check pre-Brandalf sites for org ${organizationId}: ${error.message}`,
171+
);
172+
// Cannot confirm pre-cutoff sites — fall through to v2
173+
// (brandalf=true is still set, so honor the migration).
174+
}
53175
}
54-
if (override === false) {
176+
177+
// Rows 3, 5, 7: brandalf=true without row-1 condition → v2.
178+
log.info(
179+
`LLMO mode resolution: organization ${organizationId} has brandalf=true — using v2`,
180+
);
181+
return LLMO_ONBOARDING_MODE_V2;
182+
}
183+
184+
// 2. Environment-level default (brandalf is false/missing from here on).
185+
// 'v1' is the global kill switch; anything else defaults to v2.
186+
const configuredDefault = context?.env?.LLMO_ONBOARDING_DEFAULT_VERSION;
187+
if (configuredDefault === LLMO_ONBOARDING_MODE_V1) {
188+
return LLMO_ONBOARDING_MODE_V1;
189+
}
190+
if (configuredDefault && configuredDefault !== LLMO_ONBOARDING_MODE_V2) {
191+
log.warn(
192+
`Invalid LLMO_ONBOARDING_DEFAULT_VERSION "${configuredDefault}", falling back to ${LLMO_ONBOARDING_MODE_V2}`,
193+
);
194+
}
195+
196+
// 3. Protect legacy customers: any org with a pre-cutoff site stays on v1.
197+
try {
198+
if (await hasPreBrandalfSites(organizationId, context)) {
55199
return LLMO_ONBOARDING_MODE_V1;
56200
}
57201
} catch (error) {
58202
log.warn(
59-
`Failed to resolve brandalf feature flag for organization ${organizationId}: ${error.message}`,
203+
`Failed to check pre-Brandalf sites for organization ${organizationId}: ${error.message}`,
60204
);
61205
}
62206

63-
return defaultMode;
207+
return LLMO_ONBOARDING_MODE_V2;
64208
}

test/controllers/llmo/llmo-onboarding.test.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ describe('LLMO Onboarding Functions', () => {
3737
Site: {
3838
findByBaseURL: sinon.stub(),
3939
create: sinon.stub(),
40+
// Default: no pre-cutoff sites → mode resolution returns v2 (the default).
41+
// Tests that need v1 mode should set LLMO_ONBOARDING_DEFAULT_VERSION='v1'
42+
// in context.env to use the global kill switch.
43+
allByOrganizationId: sinon.stub().resolves([]),
4044
},
4145
Organization: {
4246
findByImsOrgId: sinon.stub(),
@@ -1208,8 +1212,10 @@ describe('LLMO Onboarding Functions', () => {
12081212
expect(mockDataAccess.Site.findByBaseURL).to.have.been.calledWith('https://example.com');
12091213
expect(mockSite.getOrganizationId).to.have.been.called;
12101214
expect(mockSite.setOrganizationId).to.have.been.calledWith('new-org-456');
1211-
// Note: save() is NOT called by createOrFindSite, it's the caller's responsibility
1212-
expect(mockSite.save).to.not.have.been.called;
1215+
// LLMO-4176: re-parent must be persisted before resolveLlmoOnboardingMode
1216+
// queries Site.allByOrganizationId, otherwise a legacy site moved into a
1217+
// brand-new org would be misclassified as v2.
1218+
expect(mockSite.save).to.have.been.calledOnce;
12131219
});
12141220

12151221
it('should not update organization ID when existing site has same organization', async () => {
@@ -1408,6 +1414,13 @@ describe('LLMO Onboarding Functions', () => {
14081414
organizationId: 'org123',
14091415
});
14101416

1417+
// LLMO-4176 regression guard: resolveLlmoOnboardingMode reads
1418+
// Site.allByOrganizationId, and that read MUST happen after the site
1419+
// has been created/re-parented — otherwise a legacy site moved into a
1420+
// brand-new org gets misclassified as v2.
1421+
expect(mockDataAccess.Site.allByOrganizationId)
1422+
.to.have.been.calledAfter(mockDataAccess.Site.findByBaseURL);
1423+
14111424
// Verify site config was updated
14121425
expect(mockSite.getConfig().updateLlmoBrand).to.have.been.calledWith('Test Brand');
14131426
expect(mockSite.getConfig().updateLlmoDataFolder).to.have.been.calledWith('dev/example-com');
@@ -1446,7 +1459,7 @@ describe('LLMO Onboarding Functions', () => {
14461459
});
14471460
// Must use baseURL (matches sites.base_url), not overrideBaseURL
14481461
expect(mockUpsertBrand.firstCall.args[0].brand.urls).to.deep.equal([
1449-
{ value: 'https://example.com', type: 'url' },
1462+
{ value: 'https://example.com', type: 'base' },
14501463
]);
14511464
expect(mockLog.info).to.have.been.calledWith('Created initial brand "Test Brand" in normalized table for site site123');
14521465

@@ -1615,13 +1628,7 @@ describe('LLMO Onboarding Functions', () => {
16151628
getQueues: sinon.stub().returns({ audits: 'audit-queue' }),
16161629
};
16171630

1618-
const maybeSingle = sinon.stub().resolves({ data: { flag_value: false }, error: null });
1619-
const eqFlag = sinon.stub().returns({ maybeSingle });
1620-
const eqProduct = sinon.stub().returns({ eq: eqFlag });
1621-
const eqOrg = sinon.stub().returns({ eq: eqProduct });
1622-
const select = sinon.stub().returns({ eq: eqOrg });
1623-
mockDataAccess.services.postgrestClient.from.withArgs('feature_flags').returns({ select });
1624-
1631+
// Force v1 mode via the global kill switch — no brandalf flag lookup needed.
16251632
mockDataAccess.Organization.findByImsOrgId.resolves(mockOrganization);
16261633
mockDataAccess.Site.findByBaseURL.resolves(null);
16271634
mockDataAccess.Site.create.resolves(mockSite);
@@ -1657,7 +1664,7 @@ describe('LLMO Onboarding Functions', () => {
16571664
const context = {
16581665
dataAccess: mockDataAccess,
16591666
log: mockLog,
1660-
env: mockEnv,
1667+
env: { ...mockEnv, LLMO_ONBOARDING_DEFAULT_VERSION: 'v1' },
16611668
sqs: {
16621669
sendMessage: sinon.stub().resolves(),
16631670
},
@@ -2725,7 +2732,7 @@ describe('LLMO Onboarding Functions', () => {
27252732
expect(brand.status).to.equal('active');
27262733
expect(brand.v1SiteId).to.equal('site-123');
27272734
expect(brand.baseUrl).to.equal('https://www.example.com');
2728-
expect(brand.urls).to.deep.equal([{ value: 'https://www.example.com', type: 'url' }]);
2735+
expect(brand.urls).to.deep.equal([{ value: 'https://www.example.com', type: 'base' }]);
27292736
expect(brand.brandAliases).to.deep.equal([{ name: 'Test Brand', regions: ['gl'] }]);
27302737
expect(brand.updatedBy).to.equal('tester@example.com');
27312738
expect(brand.prompts).to.deep.equal([]);
@@ -2918,7 +2925,7 @@ describe('LLMO Onboarding Functions', () => {
29182925
expect(newBrand.status).to.equal('active');
29192926
expect(newBrand.origin).to.equal('system');
29202927
expect(newBrand.regions).to.deep.equal(['gl']);
2921-
expect(newBrand.urls).to.deep.equal([{ value: 'https://www.example.com', type: 'url' }]);
2928+
expect(newBrand.urls).to.deep.equal([{ value: 'https://www.example.com', type: 'base' }]);
29222929
expect(newBrand.brandAliases).to.deep.equal([{ name: 'New Brand', regions: ['gl'] }]);
29232930

29242931
expect(mockCustomerConfigV2Storage.writeCustomerConfigV2ToPostgres).to.have.been.calledOnce;

0 commit comments

Comments
 (0)