From 48d1f3309b6f1cca965c56dc9380d3914d685d75 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 05:10:46 +0000 Subject: [PATCH] Prepare Caterium v17.6.9 offer PDF workspace --- docs/release-manifest.json | 15 ++++++++++----- docs/releases/V17.6.9-CHANGES.txt | 8 ++++++++ package-lock.json | 4 ++-- package.json | 4 ++-- public/core/performance.js | 12 ++++++++---- public/index.html | 4 ++-- public/service-worker.js | 6 +++--- tests/app.spec.mjs | 19 ++++++++++++++++++- tests/release-check.mjs | 16 ++++++++++------ tests/static-security.mjs | 9 +++++---- 10 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 docs/releases/V17.6.9-CHANGES.txt diff --git a/docs/release-manifest.json b/docs/release-manifest.json index 211960e..61ff13a 100644 --- a/docs/release-manifest.json +++ b/docs/release-manifest.json @@ -1,6 +1,6 @@ { "app": "Caterium", - "version": "v17.6.8", + "version": "v17.6.9", "channel": "production", "schema": 17, "legacyStateKept": true, @@ -11,7 +11,7 @@ "serverReady": true, "workspaceAutoDiscovery": true, "invitesTemporarilyDisabled": false, - "pwaCache": "v73-20260908-v17-6-8-developer-console-ux", + "pwaCache": "v74-20260908-v17-6-9-offer-pdf-tabs-gallery", "fullOfferDescriptions": true, "dynamicOfferRows": true, "pdfOfferDescriptionFix": true, @@ -108,7 +108,7 @@ "catalogCompositionTildaEndpoint": "getproduct", "catalogCompositionPremiumForceRefresh": true, "catalogCompositionCacheRequiresPremium": true, - "notes": "Developer Console UX: fixed async DOM race errors, stable company numbering and deletion, accounts grouped by company, compact plan matrix, grouped production error journal.", + "notes": "Client offer workspace: PDF preview, editor and PDF templates separated into tabs; editor scroll restored; two per-offer final gallery photos can be uploaded and are used in preview/PDF.", "catalogPhotoSources": 113, "catalogPhotosStoredInCatalog": true, "catalogLegacyPhotosInCatalog": 60, @@ -246,7 +246,7 @@ "signupTrial": "14-day Full", "developerMfaInputSelectorFixed": true, "developerMfaRepeatedValidationToastsFixed": true, - "release": "20260908-v17-6-8-developer-console-ux", + "release": "20260908-v17-6-9-offer-pdf-tabs-gallery", "registrationFlow": "email-password-confirm-company-auto-login", "emailConfirmationRequired": false, "employeeInviteLinks": false, @@ -353,5 +353,10 @@ "developerJournalGroupedErrors": true, "developerJournalFiltersLocalCopies": true, "developerDomRaceFix": true, - "developerConsoleUXModule": "core/developer-console-v1768.js" + "developerConsoleUXModule": "core/developer-console-v1768.js", + "offerWorkspaceTabs": true, + "offerTemplatesSeparateTab": true, + "offerEditorScrollable": true, + "offerTwoCustomGalleryPhotos": true, + "offerWorkspaceModule": "core/offer-workspace-v1769.js" } diff --git a/docs/releases/V17.6.9-CHANGES.txt b/docs/releases/V17.6.9-CHANGES.txt new file mode 100644 index 0000000..7b9b64f --- /dev/null +++ b/docs/releases/V17.6.9-CHANGES.txt @@ -0,0 +1,8 @@ +Caterium v17.6.9 — Client Offer PDF Workspace + +- Оформление PDF вынесено из верхней части предложения в отдельную вкладку «Оформление PDF». +- Вкладка «PDF и предпросмотр» показывает только страницы предложения и кнопку скачивания, без редактора и длинной сетки шаблонов. +- «Редактор» получил собственную прокручиваемую область, поэтому длинные настройки больше не блокируют скролл. +- В редактор добавлены два независимых поля загрузки финальных фотографий «Как это выглядит на вашем столе». +- Фотографии оптимизируются в браузере, сохраняются отдельно для предложения и подставляются в предпросмотр и скачиваемый PDF. +- Кнопка «Сбросить» возвращает стандартную фотографию для каждого слота. diff --git a/package-lock.json b/package-lock.json index 74793fd..2a66a82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "caterium-app", - "version": "17.6.8", + "version": "17.6.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "caterium-app", - "version": "17.6.8", + "version": "17.6.9", "devDependencies": { "@playwright/test": "^1.51.0", "http-server": "^14.1.1", diff --git a/package.json b/package.json index 690cf79..f682db8 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "caterium-app", "private": true, - "version": "17.6.8", + "version": "17.6.9", "type": "module", "scripts": { - "check:syntax": "node --check public/app-runtime.js && node --check public/service-worker.js && node --check public/legacy/bootstrap.js && node --check public/core/sun-safe.js && node --check public/core/performance.js && node --check public/core/hotfix-v1763.js && node --check public/core/ops-ux-v1762.js && node --check public/core/ux-fixes-v1764.js && node --check public/core/pdf-engine.js && node --check public/core/classic-offer-pdf-v1767.js && node --check public/core/developer-console-v1768.js", + "check:syntax": "node --check public/app-runtime.js && node --check public/service-worker.js && node --check public/legacy/bootstrap.js && node --check public/core/sun-safe.js && node --check public/core/performance.js && node --check public/core/hotfix-v1763.js && node --check public/core/ops-ux-v1762.js && node --check public/core/ux-fixes-v1764.js && node --check public/core/pdf-engine.js && node --check public/core/classic-offer-pdf-v1767.js && node --check public/core/developer-console-v1768.js && node --check public/core/offer-workspace-v1769.js", "test:static": "node tests/static-security.mjs", "check:release": "node tests/release-check.mjs", "check:deploy": "npm run check:syntax && npm run test:static && npm run check:release", diff --git a/public/core/performance.js b/public/core/performance.js index 4379596..409d158 100644 --- a/public/core/performance.js +++ b/public/core/performance.js @@ -1,7 +1,7 @@ (()=>{ 'use strict'; - const VERSION='17.6.8'; - const RELEASE='20260908-v17-6-8-developer-console-ux'; + const VERSION='17.6.9'; + const RELEASE='20260908-v17-6-9-offer-pdf-tabs-gallery'; const critical=img=>img.closest('header,.brand,#sunCloudAuthGate,.sun-auth-gate')||img.id==='sunLoginLogo'||img.classList.contains('sun-live-catalog-logo'); const tune=img=>{ if(!(img instanceof HTMLImageElement)||critical(img))return; @@ -107,14 +107,18 @@ if(window.SunDeveloperUXV1768||document.getElementById('sunDeveloperUXV1768Script'))return; const script=document.createElement('script');script.id='sunDeveloperUXV1768Script';script.src=`core/developer-console-v1768.js?v=${RELEASE}`;script.async=true;script.onerror=()=>console.error('[Caterium] Не загрузился модуль developer-console-v1768.js');document.head.appendChild(script); } + function loadOfferWorkspace(){ + if(window.SunOfferWorkspaceV1769||document.getElementById('sunOfferWorkspaceV1769Script'))return; + const script=document.createElement('script');script.id='sunOfferWorkspaceV1769Script';script.src=`core/offer-workspace-v1769.js?v=${RELEASE}`;script.async=true;script.onerror=()=>console.error('[Caterium] Не загрузился модуль offer-workspace-v1769.js');document.head.appendChild(script); + } const start=()=>{ - loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();scan(document);startMemoryTimer(); + loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();scan(document);startMemoryTimer(); const mo=new MutationObserver(records=>{records.forEach(r=>r.addedNodes.forEach(n=>{if(n.nodeType===1)queueImageScan(n)}));}); mo.observe(document.documentElement,{childList:true,subtree:true}); document.addEventListener('click',e=>{if(e.target.closest('#sunDeveloperNavV22,[data-dev-tab],#sunDevRefresh'))scheduleMemoryRefresh(100,true)},true); window.addEventListener('sun:cloud-state-applied',()=>scheduleMemoryRefresh(180,true)); document.addEventListener('visibilitychange',()=>{if(!document.hidden&&developerVisible())scheduleMemoryRefresh(50,false)}); - window.SunPerformance={VERSION,scanImages:()=>scan(document),refreshDeveloperMemory:(force=true)=>enhanceDeveloperMemory({force}),loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,disconnect:()=>{mo.disconnect();if(memoryTimer){clearInterval(memoryTimer);memoryTimer=0}if(imageScanTimer){clearTimeout(imageScanTimer);imageScanTimer=0}pendingImageRoots.clear();}}; + window.SunPerformance={VERSION,scanImages:()=>scan(document),refreshDeveloperMemory:(force=true)=>enhanceDeveloperMemory({force}),loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,disconnect:()=>{mo.disconnect();if(memoryTimer){clearInterval(memoryTimer);memoryTimer=0}if(imageScanTimer){clearTimeout(imageScanTimer);imageScanTimer=0}pendingImageRoots.clear();}}; }; if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',start,{once:true});else start(); })(); diff --git a/public/index.html b/public/index.html index 7d34a96..044c2f1 100644 --- a/public/index.html +++ b/public/index.html @@ -71,7 +71,7 @@ button{touch-action:manipulation} #sunGlobalSearchBtn kbd{display:none!important} #sunSyncSettingsCard>div[style*="grid-template-columns"]{grid-template-columns:1fr!important} -}
Солнце Кейтеринг

Стоимость позиций0 ₽

Предоплата0 ₽

К оплате0 ₽

Заказы

МероприятиеДата и времяАдресСуммаСтатусДействия

Нажмите «Изменить», чтобы открыть заказ. Сумма, предоплата и остаток сохраняются вместе с заказом.

Склад

В этой версии каталог продуктов пополняется из составов боксов. Остатки и цены добавим следующим шагом.

Статистика

- + diff --git a/public/service-worker.js b/public/service-worker.js index 6a5d96d..1d4607a 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,8 +1,8 @@ -const CACHE='sun-catering-pwa-v73-20260908-v17-6-8-developer-console-ux'; -const VERSION='20260908-v17-6-8-developer-console-ux'; +const CACHE='sun-catering-pwa-v74-20260908-v17-6-9-offer-pdf-tabs-gallery'; +const VERSION='20260908-v17-6-9-offer-pdf-tabs-gallery'; const CORE=[ './','./index.html', - `./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/hotfix-v1763.js?v=${VERSION}`,`./core/ops-ux-v1762.js?v=${VERSION}`,`./core/ux-fixes-v1764.js?v=${VERSION}`,`./core/pdf-engine.js?v=${VERSION}`,`./core/classic-offer-pdf-v1767.js?v=${VERSION}`,`./core/developer-console-v1768.js?v=${VERSION}`,`./legacy/bootstrap.js?v=${VERSION}`,`./app-runtime.js?v=${VERSION}`, + `./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/hotfix-v1763.js?v=${VERSION}`,`./core/ops-ux-v1762.js?v=${VERSION}`,`./core/ux-fixes-v1764.js?v=${VERSION}`,`./core/pdf-engine.js?v=${VERSION}`,`./core/classic-offer-pdf-v1767.js?v=${VERSION}`,`./core/developer-console-v1768.js?v=${VERSION}`,`./core/offer-workspace-v1769.js?v=${VERSION}`,`./legacy/bootstrap.js?v=${VERSION}`,`./app-runtime.js?v=${VERSION}`, './offer-gallery/001.jpg','./offer-gallery/002.jpg', './catalog/001.jpg','./catalog/002.jpg','./catalog/003.jpg', './sun-logo.png','./caterium-login-logo.png','./pwa-icon-192.png','./pwa-icon-512.png','./manifest.webmanifest', diff --git a/tests/app.spec.mjs b/tests/app.spec.mjs index 8b61aff..c6d5c74 100644 --- a/tests/app.spec.mjs +++ b/tests/app.spec.mjs @@ -156,7 +156,7 @@ test('Developer Console memory refresh is bounded and does not react to its own const result=await page.evaluate(()=>({count:window.__rpcCount,box:document.querySelectorAll('#sunDevMemoryV1761').length,version:document.getElementById('sunDevReleaseVersion')?.textContent})); expect(result.count).toBeLessThanOrEqual(2); expect(result.box).toBe(1); - expect(result.version).toBe('17.6.8'); + expect(result.version).toBe('17.6.9'); }); test('mobile body does not overflow viewport', async ({ page }, testInfo) => { test.skip(testInfo.project.name!=='mobile-390'); await page.goto('/index.html', { waitUntil:'domcontentloaded' }); await page.waitForTimeout(500); @@ -240,3 +240,20 @@ test('v17.6.8 Developer Console UX module boots', async ({ page }) => { const result=await page.evaluate(()=>window.SunDeveloperUXV1768.checks()); expect(result.version).toBe('17.6.8'); }); + + +test('v17.6.9 offer workspace module boots', async ({ page }) => { + await page.goto('/index.html',{waitUntil:'domcontentloaded'}); + const source=fs.readFileSync(path.join(process.cwd(),'public','core','offer-workspace-v1769.js'),'utf8'); + await page.evaluate(()=>{ + document.body.innerHTML=''; + window.sunOpenClientOffer=async()=>true;window.sunOpenCurrentClientOffer=async()=>true; + window.SunClassicOfferPDFV1767={renderPages:async()=>[]};window.SunEnterprise={toast:()=>null}; + }); + await page.addScriptTag({content:source}); + await page.waitForFunction(()=>Boolean(window.SunOfferWorkspaceV1769),null,{timeout:5000}); + const result=await page.evaluate(()=>window.SunOfferWorkspaceV1769.checks()); + expect(result.version).toBe('17.6.9'); + expect(result.tabs).toBe(true); + expect(await page.locator('[data-offer-gallery-slot]').count()).toBe(2); +}); diff --git a/tests/release-check.mjs b/tests/release-check.mjs index df10a38..583b954 100644 --- a/tests/release-check.mjs +++ b/tests/release-check.mjs @@ -4,7 +4,7 @@ const root=process.cwd(), pub=path.join(root,'public'); const read=p=>fs.readFileSync(path.join(pub,p),'utf8'); const readRoot=p=>fs.readFileSync(path.join(root,p),'utf8'); let bad=0;const check=(v,m)=>{console.log(`${v?'OK':'FAIL'}: ${m}`);if(!v)bad++}; -const index=read('index.html'),runtime=read('app-runtime.js'),sw=read('service-worker.js'),css=read('core/stability-v1760.css'),performance=read('core/performance.js'),ops=read('core/ops-ux-v1762.js'),hotfix=read('core/hotfix-v1763.js'),ux=read('core/ux-fixes-v1764.js'),classic=read('core/classic-offer-pdf-v1767.js'),developerUX=read('core/developer-console-v1768.js'); +const index=read('index.html'),runtime=read('app-runtime.js'),sw=read('service-worker.js'),css=read('core/stability-v1760.css'),performance=read('core/performance.js'),ops=read('core/ops-ux-v1762.js'),hotfix=read('core/hotfix-v1763.js'),ux=read('core/ux-fixes-v1764.js'),classic=read('core/classic-offer-pdf-v1767.js'),developerUX=read('core/developer-console-v1768.js'),offerWorkspace=read('core/offer-workspace-v1769.js'); const pkg=JSON.parse(readRoot('package.json')); const lock=JSON.parse(readRoot('package-lock.json')); const releaseManifest=JSON.parse(readRoot('docs/release-manifest.json')); @@ -14,8 +14,8 @@ check(!index.includes('offer-gallery-data.js'),'blocking Base64 gallery absent') check((runtime.match(/\/Type \/Catalog/g)||[]).length===0,'runtime contains no PDF binary writer'); check(read('core/pdf-engine.js').includes('595.28')&&read('core/pdf-engine.js').includes('841.89'),'PDF engine uses A4 MediaBox'); check([...index.matchAll(/@page\{([^}]*)\}/g)].every(m=>/size:A4/i.test(m[1])),'compact @page rules use A4'); -check(sw.includes('v73-20260908-v17-6-8-developer-console-ux')&&sw.includes('classic-offer-pdf-v1767.js')&&sw.includes('developer-console-v1768.js'),'service worker cache is v17.6.8'); -check(index.includes('20260908-v17-6-8-developer-console-ux')&&index.includes('classic-offer-pdf-v1767.js')&&!index.includes('20260907-v17-6-0-stability-security'),'index cache-busting points to v17.6.8'); +check(sw.includes('v74-20260908-v17-6-9-offer-pdf-tabs-gallery')&&sw.includes('classic-offer-pdf-v1767.js')&&sw.includes('developer-console-v1768.js')&&sw.includes('offer-workspace-v1769.js'),'service worker cache is v17.6.9'); +check(index.includes('20260908-v17-6-9-offer-pdf-tabs-gallery')&&index.includes('classic-offer-pdf-v1767.js')&&!index.includes('20260907-v17-6-0-stability-security'),'index cache-busting points to v17.6.9'); check(performance.includes('SunAttachmentGuard')&&performance.includes('TARGET=2*1024*1024'),'chat photo auto-compression is versioned'); check(performance.includes("rpc('sun_dev_dashboard')")&&performance.includes('server_size')&&performance.includes('storage_size'),'Developer Console server/storage counters are versioned'); check(performance.includes('MEMORY_REFRESH_MS=30000')&&performance.includes('MEMORY_TIMEOUT_MS=8000')&&performance.includes('memoryPromise'),'Developer Console memory refresh is bounded'); @@ -39,8 +39,8 @@ check(!/sb_secret_[A-Za-z0-9_-]{20,}|service_role\s*[:=]\s*["'][A-Za-z0-9._-]{30 check(lock.version===pkg.version&&lock.packages?.['']?.version===pkg.version,'package.json and package-lock.json versions match'); check(releaseManifest.version===`v${pkg.version}`,'release manifest version matches package.json'); check(releaseManifest.channel==='production','release manifest channel is production'); -check(String(releaseManifest.pwaCache||'').includes('v73-20260908-v17-6-8-developer-console-ux'),'release manifest points to current PWA cache'); -check(['17.6.2','17.6.3','17.6.4','17.6.5','17.6.6','17.6.7','17.6.8'].every(v=>fs.existsSync(path.join(root,`docs/releases/V${v}-CHANGES.txt`))),'release notes exist through v17.6.8'); +check(String(releaseManifest.pwaCache||'').includes('v74-20260908-v17-6-9-offer-pdf-tabs-gallery'),'release manifest points to current PWA cache'); +check(['17.6.2','17.6.3','17.6.4','17.6.5','17.6.6','17.6.7','17.6.8','17.6.9'].every(v=>fs.existsSync(path.join(root,`docs/releases/V${v}-CHANGES.txt`))),'release notes exist through v17.6.9'); check(runtime.includes('CLOUD_RPC_TIMEOUT_MS=12000')&&runtime.includes('CLOUD_CONFLICT_MAX_RETRIES=4')&&runtime.includes('retryCount'),'cloud sync has timeout and capped exponential conflict retries'); check(runtime.includes("const VERSION = '17.6.5'")&&runtime.includes('ERROR_DEDUPE_MS=5*60*1000')&&runtime.includes('mirrorBusy=false')&&runtime.includes('backupBusy=false'),'stability logger uses current version, dedupe and single-flight guards'); check(runtime.includes('refreshSupportWorkspace')&&runtime.includes('sun_dev_support_snapshot'),'cloud exposes lightweight read-only support refresh'); @@ -49,7 +49,7 @@ check(performance.includes('pendingImageRoots')&&performance.includes('queueImag check(runtime.includes('explicitTemplate')&&runtime.includes("OFFER_TEMPLATE_IDS.has(explicitTemplate)"),'per-order proposal template survives render and PDF'); check(runtime.includes("else if(id==='midnight-glass')")&&runtime.includes("else if(id==='emerald-gold')")&&runtime.includes("if(id==='editorial-grid')"),'existing proposal layout sequences remain available'); check(runtime.includes('data-template-mini')&&ux.includes('data-template-mini'),'global and per-offer selectors show structural PDF previews'); -check(pkg.version==='17.6.8','package version is v17.6.8'); +check(pkg.version==='17.6.9','package version is v17.6.9'); check(classic.includes("const VERSION='17.6.7'")&&classic.includes('CLASSIC_IDS')&&classic.includes('ARCHIVE_IDS'),'classic proposal PDF module is v17.6.7'); check(runtime.includes("'warm-sun'")&&runtime.includes("'bento-cards'")&&runtime.includes("'event-story'")&&runtime.includes("'personal-letter'")&&runtime.includes("'event-ticket'")&&runtime.includes("'solar-experience'"),'10 classic proposal designs are available'); check(runtime.includes("'midnight-compact'")&&runtime.includes("'black-gold'")&&runtime.includes("'neon-emerald'"),'hidden archive proposal templates are restored'); @@ -60,4 +60,8 @@ check(developerUX.includes("const VERSION='17.6.8'")&&developerUX.includes('sun_ check(developerUX.includes('selectedAccountsWorkspace')&&developerUX.includes('sun-dev-plan-matrix'),'accounts are grouped by company and plans use compact matrix'); check(developerUX.includes('KNOWN_DOM_RACE')&&developerUX.includes('prepareAsyncRoots'),'Developer Console async DOM race is guarded'); check(releaseManifest.developerCompanyNumbers===true&&releaseManifest.developerCompanyDelete===true&&releaseManifest.developerAccountsGroupedByCompany===true&&releaseManifest.developerPlansCompactMatrix===true&&releaseManifest.developerJournalGroupedErrors===true,'release manifest records Developer Console UX changes'); +check(offerWorkspace.includes("const VERSION='17.6.9'")&&offerWorkspace.includes('sun-offer-workspace-tabs-v1769'),'offer workspace v17.6.9 is versioned'); +check(offerWorkspace.includes('PDF и предпросмотр')&&offerWorkspace.includes('Оформление PDF')&&offerWorkspace.includes('data-offer-gallery-slot'),'offer workspace separates preview/editor/templates and exposes two gallery uploads'); +check(offerWorkspace.includes('SunClassicOfferPDFV1767')&&offerWorkspace.includes('finalGallery=galleryFor'),'custom gallery is injected into PDF renderer'); +check(releaseManifest.offerWorkspaceTabs===true&&releaseManifest.offerTemplatesSeparateTab===true&&releaseManifest.offerTwoCustomGalleryPhotos===true,'release manifest records offer workspace changes'); if(bad)process.exit(1); diff --git a/tests/static-security.mjs b/tests/static-security.mjs index 5ebb0a4..f439564 100644 --- a/tests/static-security.mjs +++ b/tests/static-security.mjs @@ -6,7 +6,7 @@ const readPub=p=>fs.readFileSync(path.join(pub,p),'utf8'); const readRoot=p=>fs.readFileSync(path.join(root,p),'utf8'); const fail=m=>{console.error('FAIL:',m);process.exitCode=1}; const ok=m=>console.log('OK:',m); -const html=readPub('index.html'),legacy=readPub('legacy/bootstrap.js'),runtime=readPub('app-runtime.js'),safe=readPub('core/sun-safe.js'),sw=readPub('service-worker.js'),performance=readPub('core/performance.js'),ops=readPub('core/ops-ux-v1762.js'),hotfix=readPub('core/hotfix-v1763.js'),ux=readPub('core/ux-fixes-v1764.js'),classic=readPub('core/classic-offer-pdf-v1767.js'),developerUX=readPub('core/developer-console-v1768.js'); +const html=readPub('index.html'),legacy=readPub('legacy/bootstrap.js'),runtime=readPub('app-runtime.js'),safe=readPub('core/sun-safe.js'),sw=readPub('service-worker.js'),performance=readPub('core/performance.js'),ops=readPub('core/ops-ux-v1762.js'),hotfix=readPub('core/hotfix-v1763.js'),ux=readPub('core/ux-fixes-v1764.js'),classic=readPub('core/classic-offer-pdf-v1767.js'),developerUX=readPub('core/developer-console-v1768.js'),offerWorkspace=readPub('core/offer-workspace-v1769.js'); if(!html.includes('core/sun-safe.js'))fail('SunSafe must load before legacy modules');else ok('shared SunSafe loaded'); if(html.includes('offer-gallery-data.js')||fs.existsSync(path.join(pub,'offer-gallery-data.js')))fail('blocking offer-gallery-data.js still present');else ok('base64 gallery removed'); for(const raw of ['${b.name}','${o.event}','${o.address||','value="${x[0]}"','value="${x[2]}"']) if(legacy.includes(raw)) fail(`legacy bootstrap contains raw HTML interpolation ${raw}`); @@ -27,8 +27,8 @@ if(current!==113)fail(`current catalog photo count ${current}, expected 113`);el if(legacyCount!==60)fail(`legacy catalog photo count ${legacyCount}, expected 60`);else ok('60 legacy catalog photos'); const gallery=fs.readdirSync(path.join(pub,'offer-gallery')).filter(x=>/\.jpg$/i.test(x)); if(gallery.length!==2)fail(`offer gallery contains ${gallery.length} jpg files, expected 2`);else ok('offer gallery trimmed'); -if(!sw.includes('v17-6-8-developer-console-ux')||!sw.includes('developer-console-v1768.js')||!sw.includes('classic-offer-pdf-v1767.js')||sw.includes('offer-gallery-data.js'))fail('service worker cache is stale');else ok('PWA cache updated to v17.6.8'); -if(html.includes('20260907-v17-6-0-stability-security')||!html.includes('20260908-v17-6-8-developer-console-ux')||!html.includes('classic-offer-pdf-v1767.js'))fail('index still serves stale core asset version');else ok('index cache-busting is current'); +if(!sw.includes('v17-6-9-offer-pdf-tabs-gallery')||!sw.includes('offer-workspace-v1769.js')||!sw.includes('developer-console-v1768.js')||!sw.includes('classic-offer-pdf-v1767.js')||sw.includes('offer-gallery-data.js'))fail('service worker cache is stale');else ok('PWA cache updated to v17.6.9'); +if(html.includes('20260907-v17-6-0-stability-security')||!html.includes('20260908-v17-6-9-offer-pdf-tabs-gallery')||!html.includes('classic-offer-pdf-v1767.js'))fail('index still serves stale core asset version');else ok('index cache-busting is current'); if(!performance.includes('SunAttachmentGuard')||!performance.includes('MAX_SIDE=2048'))fail('chat photo compression guard missing');else ok('chat photo compression guard present'); if(!performance.includes("rpc('sun_dev_dashboard')")||!performance.includes('storage_size')||!performance.includes('server_size'))fail('Developer Console memory counters missing');else ok('Developer Console memory counters present'); if(performance.includes('records.forEach(r=>r.addedNodes.forEach(n=>{if(n.nodeType===1)scan(n)}));enhanceDeveloperMemory()'))fail('Developer Console memory refresh is still coupled to MutationObserver');else ok('Developer Console memory refresh loop removed'); @@ -45,5 +45,6 @@ if(!hotfix.includes('checkPlatformAdmin?.(false)')||!hotfix.includes('},10000);' if(!ux.includes('sunMenuIconV1766')||!ux.includes('sun-offer-template-mini-editorial-grid')||!runtime.includes('explicitTemplate'))fail('v17.6.6 proposal/menu markers missing');else ok('v17.6.6 proposal/menu markers present'); if(!classic.includes("const VERSION='17.6.7'")||!classic.includes('CLASSIC_IDS')||!classic.includes('ARCHIVE_IDS')||!classic.includes('renderPages'))fail('v17.6.7 classic PDF module missing');else ok('v17.6.7 classic PDF module present'); if(!developerUX.includes("const VERSION='17.6.8'")||!developerUX.includes('sun_dev_delete_company_v1768')||!developerUX.includes('sun_dev_error_groups_v1768')||!developerUX.includes('selectedAccountsWorkspace')||!developerUX.includes('sun-dev-plan-matrix')||!developerUX.includes('KNOWN_DOM_RACE'))fail('v17.6.8 Developer Console UX module missing');else ok('v17.6.8 Developer Console UX module present'); -if(/service_role\s*[:=]\s*['"][A-Za-z0-9._-]{20,}/i.test(ops+hotfix+ux+classic+developerUX)||/eyJ[a-zA-Z0-9_-]{30,}/.test(ops+hotfix+ux+classic+developerUX))fail('possible secret in ops/hotfix/ux/classic/developer module');else ok('ops/hotfix/ux/classic/developer modules have no hard-coded secret'); +if(!offerWorkspace.includes("const VERSION='17.6.9'")||!offerWorkspace.includes('data-offer-workspace-tab=\"templates\"')||!offerWorkspace.includes('data-offer-gallery-slot')||!offerWorkspace.includes('sunOfferGalleryOverridesV1769'))fail('v17.6.9 offer workspace module missing');else ok('v17.6.9 offer workspace module present'); +if(/service_role\s*[:=]\s*['"][A-Za-z0-9._-]{20,}/i.test(ops+hotfix+ux+classic+developerUX+offerWorkspace)||/eyJ[a-zA-Z0-9_-]{30,}/.test(ops+hotfix+ux+classic+developerUX+offerWorkspace))fail('possible secret in ops/hotfix/ux/classic/developer/offer module');else ok('ops/hotfix/ux/classic/developer/offer modules have no hard-coded secret'); if(process.exitCode)process.exit(process.exitCode); \ No newline at end of file