From 8cc9e0ff5bf21ee746e6d7f22413de9ed9d7c78e Mon Sep 17 00:00:00 2001 From: Gabriel Eluan Date: Thu, 28 May 2026 15:53:59 -0300 Subject: [PATCH 1/3] feat(intsch): emit dpPreview=true on non-master workspaces (DPT-67) Adds workspace-driven QA mode for Delivery Promises: the Intsch client now appends `dpPreview=true` to product-search and facets requests whenever the current IO workspace is not `master`. Storefronts running QA in a workspace get DP activated end-to-end on the IS API without the store having to flip the persisted `deliveryPromisesEnabled` setting. Production traffic in `master` is untouched. - New `shouldInjectDPPreview(workspace)` helper centralizes the policy (`master` and undefined/empty values stay opted out). - `dpPreview` added to the IS API query keys allowlist so the param survives `filterByAllowedIntelligentSearchQueryKeys`. - Coverage for the helper and the allowlist behavior. Refs: https://vtex-dev.atlassian.net/browse/DPT-67 Co-Authored-By: Claude Opus 4.7 --- node/clients/intsch/index.ts | 17 ++++++++ node/clients/intsch/utils.test.ts | 68 +++++++++++++++++++++++++++++++ node/clients/intsch/utils.ts | 22 ++++++++++ 3 files changed, 107 insertions(+) create mode 100644 node/clients/intsch/utils.test.ts diff --git a/node/clients/intsch/index.ts b/node/clients/intsch/index.ts index b23fa0ea..0f7d6128 100644 --- a/node/clients/intsch/index.ts +++ b/node/clients/intsch/index.ts @@ -30,6 +30,7 @@ import { parseState } from '../../utils/searchState' import { filterUndefinedNonNull, filterByAllowedIntelligentSearchQueryKeys, + shouldInjectDPPreview, } from './utils' export class Intsch extends JanusClient implements IIntelligentSearchClient { @@ -171,6 +172,13 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { const requestPath = `/api/intelligent-search/v1/product-search/${path}` + // DPT-67: emit dpPreview=true on non-master workspaces so QA traffic + // exercises the DP code path end-to-end without flipping the persisted + // `deliveryPromisesEnabled` store setting. + const dpPreview = shouldInjectDPPreview(this.context.workspace) + ? 'true' + : undefined + const merged = filterUndefinedNonNull({ sc: params.salesChannel ? params.salesChannel : segmentParams?.sc, regionId: params.regionId ?? segmentParams?.regionId, @@ -208,6 +216,7 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { : undefined, simulationBehavior: params.simulationBehavior ?? undefined, variant: params.variant, + dpPreview, ...parseState(searchState), }) @@ -253,6 +262,13 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { const facetsPath = `/api/intelligent-search/v1/facets/${path}` + // DPT-67: emit dpPreview=true on non-master workspaces so QA traffic + // exercises the DP code path end-to-end without flipping the persisted + // `deliveryPromisesEnabled` store setting. + const dpPreview = shouldInjectDPPreview(this.context.workspace) + ? 'true' + : undefined + const merged = filterUndefinedNonNull({ sc: segmentParams?.sc, regionId: params.regionId ?? segmentParams?.regionId, @@ -272,6 +288,7 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { locale: this.locale ?? segmentParams?.locale, bgy_leap: leap ? 'true' : undefined, variant: params.variant, + dpPreview, ...parseState(searchState), } as Record) diff --git a/node/clients/intsch/utils.test.ts b/node/clients/intsch/utils.test.ts new file mode 100644 index 00000000..f05b8357 --- /dev/null +++ b/node/clients/intsch/utils.test.ts @@ -0,0 +1,68 @@ +import { + filterByAllowedIntelligentSearchQueryKeys, + filterUndefinedNonNull, + shouldInjectDPPreview, +} from './utils' + +describe('filterUndefinedNonNull', () => { + it('drops undefined and null values', () => { + expect( + filterUndefinedNonNull({ a: 1, b: undefined, c: null, d: 'x' }) + ).toEqual({ a: 1, d: 'x' }) + }) + + it('keeps falsy-but-meaningful values (false, "", 0)', () => { + expect(filterUndefinedNonNull({ a: false, b: '', c: 0 })).toEqual({ + a: false, + b: '', + c: 0, + }) + }) +}) + +describe('filterByAllowedIntelligentSearchQueryKeys', () => { + it('keeps known IS API query keys and drops unknown ones', () => { + const result = filterByAllowedIntelligentSearchQueryKeys({ + query: 'shoes', + foo: 'bar', + regionId: 'r1', + }) + expect(result).toEqual({ query: 'shoes', regionId: 'r1' }) + }) + + it('accepts the DPT-67 dpPreview key on the allowlist', () => { + const result = filterByAllowedIntelligentSearchQueryKeys({ + dpPreview: 'true', + ignored: 'value', + }) + expect(result).toEqual({ dpPreview: 'true' }) + }) +}) + +/** + * DPT-67: workspace-driven QA mode. The storefront emits `dpPreview=true` on + * non-`master` workspaces so the IS API activates the Delivery Promises code + * path without the store having to flip `deliveryPromisesEnabled`. Production + * traffic in `master` must never carry the param. + */ +describe('shouldInjectDPPreview', () => { + it('returns true for a typical QA workspace', () => { + expect(shouldInjectDPPreview('qa-store')).toBe(true) + }) + + it('returns true for a dev workspace', () => { + expect(shouldInjectDPPreview('dev')).toBe(true) + }) + + it('returns false for master', () => { + expect(shouldInjectDPPreview('master')).toBe(false) + }) + + it('returns false when the workspace is undefined', () => { + expect(shouldInjectDPPreview(undefined)).toBe(false) + }) + + it('returns false when the workspace is an empty string', () => { + expect(shouldInjectDPPreview('')).toBe(false) + }) +}) diff --git a/node/clients/intsch/utils.ts b/node/clients/intsch/utils.ts index 075b353c..abf6920f 100644 --- a/node/clients/intsch/utils.ts +++ b/node/clients/intsch/utils.ts @@ -90,8 +90,30 @@ export const INTELLIGENT_SEARCH_PRODUCT_QUERY_KEYS = new Set([ 'priceTables', 'simulationBehavior', 'variant', + // DPT-67: per-request override that activates the Delivery Promises code + // path in the IS API without flipping the persisted `deliveryPromisesEnabled` + // store setting. Emitted automatically on non-`master` workspaces — see + // {@link shouldInjectDPPreview}. + 'dpPreview', ]) +/** + * Whether the IS API call should carry the `dpPreview=true` query param + * for this request. + * + * Workspaces other than `master` are treated as QA environments — they get + * DP activated end-to-end so the customer can validate the feature before + * flipping the persisted store setting. `master` traffic is left untouched + * to guarantee no behavioral change in production until the store explicitly + * opts in via Store Search Settings. + * + * See DPT-67 for the rationale behind decoupling activation from the + * `deliveryPromisesEnabled` flag. + */ +export function shouldInjectDPPreview(workspace: string | undefined): boolean { + return workspace !== undefined && workspace !== '' && workspace !== 'master' +} + export function filterByAllowedIntelligentSearchQueryKeys( obj: Record, allowedKeys: Set = INTELLIGENT_SEARCH_PRODUCT_QUERY_KEYS From 9bbd8b12a9a594452267631bf544f58361ddc223 Mon Sep 17 00:00:00 2001 From: Gabriel Eluan Date: Fri, 29 May 2026 10:38:47 -0300 Subject: [PATCH 2/3] docs(dp-preview): trim verbose comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tighten the comments added in the previous commit. Helper names and the PR description carry the rationale — inline blocks were repeating each other. Co-Authored-By: Claude Opus 4.7 --- node/clients/intsch/index.ts | 6 ------ node/clients/intsch/utils.ts | 18 +++--------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/node/clients/intsch/index.ts b/node/clients/intsch/index.ts index 0f7d6128..4cb8c576 100644 --- a/node/clients/intsch/index.ts +++ b/node/clients/intsch/index.ts @@ -172,9 +172,6 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { const requestPath = `/api/intelligent-search/v1/product-search/${path}` - // DPT-67: emit dpPreview=true on non-master workspaces so QA traffic - // exercises the DP code path end-to-end without flipping the persisted - // `deliveryPromisesEnabled` store setting. const dpPreview = shouldInjectDPPreview(this.context.workspace) ? 'true' : undefined @@ -262,9 +259,6 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { const facetsPath = `/api/intelligent-search/v1/facets/${path}` - // DPT-67: emit dpPreview=true on non-master workspaces so QA traffic - // exercises the DP code path end-to-end without flipping the persisted - // `deliveryPromisesEnabled` store setting. const dpPreview = shouldInjectDPPreview(this.context.workspace) ? 'true' : undefined diff --git a/node/clients/intsch/utils.ts b/node/clients/intsch/utils.ts index abf6920f..9d254de4 100644 --- a/node/clients/intsch/utils.ts +++ b/node/clients/intsch/utils.ts @@ -90,25 +90,13 @@ export const INTELLIGENT_SEARCH_PRODUCT_QUERY_KEYS = new Set([ 'priceTables', 'simulationBehavior', 'variant', - // DPT-67: per-request override that activates the Delivery Promises code - // path in the IS API without flipping the persisted `deliveryPromisesEnabled` - // store setting. Emitted automatically on non-`master` workspaces — see - // {@link shouldInjectDPPreview}. 'dpPreview', ]) /** - * Whether the IS API call should carry the `dpPreview=true` query param - * for this request. - * - * Workspaces other than `master` are treated as QA environments — they get - * DP activated end-to-end so the customer can validate the feature before - * flipping the persisted store setting. `master` traffic is left untouched - * to guarantee no behavioral change in production until the store explicitly - * opts in via Store Search Settings. - * - * See DPT-67 for the rationale behind decoupling activation from the - * `deliveryPromisesEnabled` flag. + * Whether the IS API call should carry `dpPreview=true`. Non-`master` + * workspaces are treated as QA and get DP activated end-to-end without + * the store flipping `deliveryPromisesEnabled`. */ export function shouldInjectDPPreview(workspace: string | undefined): boolean { return workspace !== undefined && workspace !== '' && workspace !== 'master' From 77455f6ae170bb86245a5458112a433ecbc50629 Mon Sep 17 00:00:00 2001 From: Gabriel Eluan Date: Thu, 18 Jun 2026 10:42:35 -0300 Subject: [PATCH 3/3] refactor(dp-preview): gate dpPreview on context.production, not workspace name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per review: a workspace can be non-master yet still production, so keying the QA override off the workspace name would leak dpPreview into real production traffic on named production workspaces. Gate on `context.production` instead — only non-production workspaces emit the param. Co-Authored-By: Claude Opus 4.7 --- node/clients/intsch/index.ts | 4 ++-- node/clients/intsch/utils.test.ts | 27 ++++++++------------------- node/clients/intsch/utils.ts | 12 +++++++----- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/node/clients/intsch/index.ts b/node/clients/intsch/index.ts index 4cb8c576..39ef13a8 100644 --- a/node/clients/intsch/index.ts +++ b/node/clients/intsch/index.ts @@ -172,7 +172,7 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { const requestPath = `/api/intelligent-search/v1/product-search/${path}` - const dpPreview = shouldInjectDPPreview(this.context.workspace) + const dpPreview = shouldInjectDPPreview(this.context.production) ? 'true' : undefined @@ -259,7 +259,7 @@ export class Intsch extends JanusClient implements IIntelligentSearchClient { const facetsPath = `/api/intelligent-search/v1/facets/${path}` - const dpPreview = shouldInjectDPPreview(this.context.workspace) + const dpPreview = shouldInjectDPPreview(this.context.production) ? 'true' : undefined diff --git a/node/clients/intsch/utils.test.ts b/node/clients/intsch/utils.test.ts index f05b8357..17cd69a4 100644 --- a/node/clients/intsch/utils.test.ts +++ b/node/clients/intsch/utils.test.ts @@ -40,29 +40,18 @@ describe('filterByAllowedIntelligentSearchQueryKeys', () => { }) /** - * DPT-67: workspace-driven QA mode. The storefront emits `dpPreview=true` on - * non-`master` workspaces so the IS API activates the Delivery Promises code + * DPT-67: production-driven QA mode. The storefront emits `dpPreview=true` on + * non-production workspaces so the IS API activates the Delivery Promises code * path without the store having to flip `deliveryPromisesEnabled`. Production - * traffic in `master` must never carry the param. + * traffic must never carry the param — including named workspaces promoted to + * production, not just `master`. */ describe('shouldInjectDPPreview', () => { - it('returns true for a typical QA workspace', () => { - expect(shouldInjectDPPreview('qa-store')).toBe(true) + it('returns true for a non-production (QA/dev) workspace', () => { + expect(shouldInjectDPPreview(false)).toBe(true) }) - it('returns true for a dev workspace', () => { - expect(shouldInjectDPPreview('dev')).toBe(true) - }) - - it('returns false for master', () => { - expect(shouldInjectDPPreview('master')).toBe(false) - }) - - it('returns false when the workspace is undefined', () => { - expect(shouldInjectDPPreview(undefined)).toBe(false) - }) - - it('returns false when the workspace is an empty string', () => { - expect(shouldInjectDPPreview('')).toBe(false) + it('returns false for a production workspace', () => { + expect(shouldInjectDPPreview(true)).toBe(false) }) }) diff --git a/node/clients/intsch/utils.ts b/node/clients/intsch/utils.ts index 9d254de4..07fe1f91 100644 --- a/node/clients/intsch/utils.ts +++ b/node/clients/intsch/utils.ts @@ -94,12 +94,14 @@ export const INTELLIGENT_SEARCH_PRODUCT_QUERY_KEYS = new Set([ ]) /** - * Whether the IS API call should carry `dpPreview=true`. Non-`master` - * workspaces are treated as QA and get DP activated end-to-end without - * the store flipping `deliveryPromisesEnabled`. + * Whether the IS API call should carry `dpPreview=true`. Non-production + * workspaces are treated as QA and get DP activated end-to-end without the + * store flipping `deliveryPromisesEnabled`. Production workspaces never carry + * the param — including named workspaces promoted to production, not just + * `master`. */ -export function shouldInjectDPPreview(workspace: string | undefined): boolean { - return workspace !== undefined && workspace !== '' && workspace !== 'master' +export function shouldInjectDPPreview(production: boolean): boolean { + return !production } export function filterByAllowedIntelligentSearchQueryKeys(