From ee378b3b1af25bc454bad819c9d9eff645977084 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:37:14 +0000 Subject: [PATCH] Caterium v17.7.1 password security --- docs/release-manifest.json | 14 +++++++++----- docs/releases/V17.7.1-CHANGES.txt | 10 ++++++++++ package-lock.json | 4 ++-- package.json | 4 ++-- public/core/performance.js | 12 ++++++++---- public/index.html | 4 ++-- public/service-worker.js | 4 ++-- tests/app.spec.mjs | 30 ++++++++++++++++++++++++++++++ tests/release-check.mjs | 8 ++++++++ 9 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 docs/releases/V17.7.1-CHANGES.txt diff --git a/docs/release-manifest.json b/docs/release-manifest.json index 704c887..802fe72 100644 --- a/docs/release-manifest.json +++ b/docs/release-manifest.json @@ -1,6 +1,6 @@ { "app": "Caterium", - "version": "v17.7.0", + "version": "v17.7.1", "channel": "production", "schema": 17, "legacyStateKept": true, @@ -11,7 +11,7 @@ "serverReady": true, "workspaceAutoDiscovery": true, "invitesTemporarilyDisabled": false, - "pwaCache": "v75-20260908-v17-7-0-architecture-foundation", + "pwaCache": "v76-20260908-v17-7-1-password-security", "fullOfferDescriptions": true, "dynamicOfferRows": true, "pdfOfferDescriptionFix": true, @@ -108,7 +108,7 @@ "catalogCompositionTildaEndpoint": "getproduct", "catalogCompositionPremiumForceRefresh": true, "catalogCompositionCacheRequiresPremium": true, - "notes": "Architecture foundation: explicit data layer, server-side order automation with legacy/cloud compatibility, telemetry hygiene, current stability version, regression checks.", + "notes": "Account security: temporary-password employees are blocked by an independent mandatory password-change gate that survives workspace loading; every signed-in account gets Change password in Profile.", "catalogPhotoSources": 113, "catalogPhotosStoredInCatalog": true, "catalogLegacyPhotosInCatalog": 60, @@ -246,7 +246,7 @@ "signupTrial": "14-day Full", "developerMfaInputSelectorFixed": true, "developerMfaRepeatedValidationToastsFixed": true, - "release": "20260908-v17-7-0-architecture-foundation", + "release": "20260908-v17-7-1-password-security", "registrationFlow": "email-password-confirm-company-auto-login", "emailConfirmationRequired": false, "employeeInviteLinks": false, @@ -367,5 +367,9 @@ "browserOrderAutomationCloudDisabled": true, "errorTelemetryRejectsLocalFile": true, "errorTelemetryServerDedupMinutes": 5, - "errorTelemetryRetentionDays": 30 + "errorTelemetryRetentionDays": 30, + "forcedTemporaryPasswordChange": true, + "passwordChangeInEveryAccount": true, + "passwordMinimumLength": 8, + "passwordChangeRequiresCurrentPassword": true } diff --git a/docs/releases/V17.7.1-CHANGES.txt b/docs/releases/V17.7.1-CHANGES.txt new file mode 100644 index 0000000..6e9c932 --- /dev/null +++ b/docs/releases/V17.7.1-CHANGES.txt @@ -0,0 +1,10 @@ +Caterium v17.7.1 — Account password security +Date: 2026-09-08 + +1. First login with an employee temporary password opens an independent mandatory password-change security gate. +2. The mandatory gate is not owned by the workspace/auth loading DOM, so workspace loading cannot make it disappear. +3. Until a new password is saved, the user cannot continue into the application; only Sign out is available. +4. Every signed-in account gets Profile → Security → Change password. +5. Normal password change verifies the current password, requires a minimum of 8 characters and confirmation. +6. Successful first-login change clears user_metadata.must_change_password and refreshes the session. +7. PWA cache v76 / 20260908-v17-7-1-password-security. diff --git a/package-lock.json b/package-lock.json index d67ce2f..31c056e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "caterium-app", - "version": "17.7.0", + "version": "17.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "caterium-app", - "version": "17.7.0", + "version": "17.7.1", "devDependencies": { "@playwright/test": "^1.51.0", "http-server": "^14.1.1", diff --git a/package.json b/package.json index e5f6448..830e3f5 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "caterium-app", "private": true, - "version": "17.7.0", + "version": "17.7.1", "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/data-layer-v1770.js && node --check public/core/server-automation-v1770.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", + "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/data-layer-v1770.js && node --check public/core/server-automation-v1770.js && node --check public/core/account-security-v1771.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 bbbfe11..1c13bc0 100644 --- a/public/core/performance.js +++ b/public/core/performance.js @@ -1,7 +1,7 @@ (()=>{ 'use strict'; - const VERSION='17.7.0'; - const RELEASE='20260908-v17-7-0-architecture-foundation'; + const VERSION='17.7.1'; + const RELEASE='20260908-v17-7-1-password-security'; 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; @@ -119,14 +119,18 @@ 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); } + function loadAccountSecurity(){ + if(window.CateriumAccountSecurityV1771||document.getElementById('cateriumAccountSecurityV1771Script'))return; + const script=document.createElement('script');script.id='cateriumAccountSecurityV1771Script';script.src=`core/account-security-v1771.js?v=${RELEASE}`;script.async=true;script.onerror=()=>console.error('[Caterium] Не загрузился модуль account-security-v1771.js');document.head.appendChild(script); + } const start=()=>{ - loadDataLayer();loadServerAutomation();loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();scan(document);startMemoryTimer(); + loadDataLayer();loadServerAutomation();loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();loadAccountSecurity();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}),loadDataLayer,loadServerAutomation,loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,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}),loadDataLayer,loadServerAutomation,loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,loadAccountSecurity,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 b864e91..0def4d9 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 9654b06..2203c8b 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,5 +1,5 @@ -const CACHE='sun-catering-pwa-v75-20260908-v17-7-0-architecture-foundation'; -const VERSION='20260908-v17-7-0-architecture-foundation'; +const CACHE='sun-catering-pwa-v76-20260908-v17-7-1-password-security'; +const VERSION='20260908-v17-7-1-password-security'; const CORE=[ './','./index.html', `./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/data-layer-v1770.js?v=${VERSION}`,`./core/server-automation-v1770.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}`, diff --git a/tests/app.spec.mjs b/tests/app.spec.mjs index 399ecc4..29fef3c 100644 --- a/tests/app.spec.mjs +++ b/tests/app.spec.mjs @@ -273,3 +273,33 @@ test('v17.7.0 server automation applies returned normalized orders through data await page.waitForFunction(()=>Boolean(window.CateriumServerAutomationV1770));await page.evaluate(async()=>{window.__signed=true;await window.CateriumServerAutomationV1770.run({force:true})}); expect(await page.evaluate(()=>window.__applied)).toEqual([{id:8,status:'Отдан заказчику'}]); }); + + +test('v17.7.1 temporary-password account gets persistent mandatory password gate', async ({ page }) => { + await page.goto('/index.html',{waitUntil:'domcontentloaded'}); + await page.evaluate(()=>{ + window.CateriumAccountSecurityV1771=undefined; + window.SunCloudV2={getSession:()=>({user:{id:'u1',email:'employee@example.com',user_metadata:{must_change_password:true},app_metadata:{}}}),getClient:()=>({auth:{getUser:async()=>({data:{user:{id:'u1',email:'employee@example.com',user_metadata:{must_change_password:true},app_metadata:{}}}}),updateUser:async()=>({data:{user:{}},error:null}),refreshSession:async()=>({})}})}; + }); + const src=fs.readFileSync(path.join(process.cwd(),'public/core/account-security-v1771.js'),'utf8');await page.addScriptTag({content:src}); + await page.waitForSelector('#cateriumPasswordGateV1771'); + expect(await page.locator('#cateriumPasswordGateV1771').isVisible()).toBe(true); + expect(await page.locator('#catPasswordCancelV1771').count()).toBe(0); + await page.evaluate(()=>{document.body.insertAdjacentHTML('beforeend','
')}); + await page.waitForTimeout(120); + expect(await page.locator('#cateriumPasswordGateV1771').isVisible()).toBe(true); +}); + +test('v17.7.1 every signed-in account gets Change password in Profile', async ({ page }) => { + await page.goto('/index.html',{waitUntil:'domcontentloaded'}); + await page.evaluate(()=>{ + window.CateriumAccountSecurityV1771=undefined; + document.body.insertAdjacentHTML('beforeend','

Профиль

user@example.com
'); + window.SunCloudV2={getSession:()=>({user:{id:'u2',email:'user@example.com',user_metadata:{},app_metadata:{}}}),getClient:()=>({auth:{getUser:async()=>({data:{user:{id:'u2',email:'user@example.com',user_metadata:{},app_metadata:{}}}}),signInWithPassword:async()=>({error:null}),updateUser:async()=>({data:{user:{}},error:null}),refreshSession:async()=>({})}})}; + }); + const src=fs.readFileSync(path.join(process.cwd(),'public/core/account-security-v1771.js'),'utf8');await page.addScriptTag({content:src}); + await page.waitForSelector('#catProfilePasswordV1771'); + expect(await page.locator('#catProfilePasswordV1771').textContent()).toContain('Сменить пароль'); + await page.locator('#catProfilePasswordV1771').click(); + await expect(page.locator('#catCurrentPasswordV1771')).toBeVisible(); +}); diff --git a/tests/release-check.mjs b/tests/release-check.mjs index 882ccfd..eff2b4f 100644 --- a/tests/release-check.mjs +++ b/tests/release-check.mjs @@ -72,3 +72,11 @@ check(ux.includes('CateriumServerAutomationV1770?.enabled'),'cloud browser auto check(runtime.includes("const VERSION = '17.7.0'")&&runtime.includes("v17.7.0 Architecture Foundation"),'stability logger reports v17.7.0'); check(fs.existsSync(path.join(root,'ops/sql/SUPABASE-V17.7.0-SERVER-ORDER-AUTOMATION.sql'))&&fs.existsSync(path.join(root,'ops/sql/SUPABASE-V17.7.0-ERROR-TELEMETRY-HYGIENE.sql')),'v17.7.0 server migrations are versioned'); if(bad)process.exit(1); + +check(pkg.version==='17.7.1','package version is v17.7.1'); +check(index.includes('20260908-v17-7-1-password-security'),'index cache token is v17.7.1'); +check(sw.includes('v76-20260908-v17-7-1-password-security')&&sw.includes('account-security-v1771.js'),'service worker contains account security v17.7.1'); +const accountSecurity=fs.readFileSync(path.join(root,'public/core/account-security-v1771.js'),'utf8'); +check(accountSecurity.includes('must_change_password')&&accountSecurity.includes('cat-password-required-v1771')&&accountSecurity.includes('Сменить пароль'),'account security includes mandatory temporary-password gate and profile password change'); +check(accountSecurity.includes('signInWithPassword')&&accountSecurity.includes('auth.updateUser')&&accountSecurity.includes('минимум 8 символов'),'password change verifies current password and updates Supabase Auth'); +check(performance.includes('loadAccountSecurity')&&performance.includes('account-security-v1771.js'),'performance loader installs account security');