Add v17.7.1 password security release patcher

This commit is contained in:
pavlov346346-source 2026-09-08 16:36:47 +03:00
parent 10d022641e
commit 893c7c60cd

View File

@ -0,0 +1,24 @@
import fs from 'node:fs';
const VERSION='17.7.1',RELEASE='20260908-v17-7-1-password-security';
const read=f=>fs.readFileSync(f,'utf8'),write=(f,s)=>fs.writeFileSync(f,s);
const once=(s,a,b,label)=>{const n=s.split(a).length-1;if(n!==1)throw new Error(`${label}: expected 1 match, got ${n}`);return s.replace(a,b)};
let perf=read('public/core/performance.js');
perf=once(perf," const VERSION='17.7.0';\n const RELEASE='20260908-v17-7-0-architecture-foundation';",` const VERSION='${VERSION}';\n const RELEASE='${RELEASE}';`,'performance version');
perf=once(perf," function loadOfferWorkspace(){\n if(window.SunOfferWorkspaceV1769||document.getElementById('sunOfferWorkspaceV1769Script'))return;\n 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);\n }"," function loadOfferWorkspace(){\n if(window.SunOfferWorkspaceV1769||document.getElementById('sunOfferWorkspaceV1769Script'))return;\n 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);\n }\n function loadAccountSecurity(){\n if(window.CateriumAccountSecurityV1771||document.getElementById('cateriumAccountSecurityV1771Script'))return;\n 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);\n }",'security loader');
perf=once(perf," loadDataLayer();loadServerAutomation();loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();scan(document);startMemoryTimer();"," loadDataLayer();loadServerAutomation();loadHotfix();loadOpsUX();loadUXFix();loadDeveloperUX();loadOfferWorkspace();loadAccountSecurity();scan(document);startMemoryTimer();",'security startup');
perf=once(perf,"loadDataLayer,loadServerAutomation,loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,disconnect","loadDataLayer,loadServerAutomation,loadHotfix,loadOpsUX,loadUXFix,loadDeveloperUX,loadOfferWorkspace,loadAccountSecurity,disconnect",'security export');
write('public/core/performance.js',perf);
let pkg=JSON.parse(read('package.json'));pkg.version=VERSION;pkg.scripts['check:syntax']=pkg.scripts['check:syntax'].replace('public/core/server-automation-v1770.js','public/core/server-automation-v1770.js && node --check public/core/account-security-v1771.js');write('package.json',JSON.stringify(pkg,null,2)+'\n');
let lock=JSON.parse(read('package-lock.json'));lock.version=VERSION;if(lock.packages?.[''])lock.packages[''].version=VERSION;write('package-lock.json',JSON.stringify(lock,null,2)+'\n');
let index=read('public/index.html');index=index.split('20260908-v17-7-0-architecture-foundation').join(RELEASE);write('public/index.html',index);
let sw=read('public/service-worker.js');sw=sw.replace(/const CACHE='sun-catering-pwa-v\d+-[^']+';\nconst VERSION='[^']+';/,`const CACHE='sun-catering-pwa-v76-${RELEASE}';\nconst VERSION='${RELEASE}';`);if(!sw.includes("'core/account-security-v1771.js'"))sw=sw.replace("'core/server-automation-v1770.js',","'core/server-automation-v1770.js',\n 'core/account-security-v1771.js',");write('public/service-worker.js',sw);
let manifest=JSON.parse(read('docs/release-manifest.json'));Object.assign(manifest,{version:'v17.7.1',release:RELEASE,pwaCache:`v76-${RELEASE}`,forcedTemporaryPasswordChange:true,passwordChangeInEveryAccount:true,passwordMinimumLength:8,passwordChangeRequiresCurrentPassword:true,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.'});write('docs/release-manifest.json',JSON.stringify(manifest,null,2)+'\n');
write('docs/releases/V17.7.1-CHANGES.txt',`Caterium v17.7.1 — Account password security\nDate: 2026-09-08\n\n1. First login with an employee temporary password opens an independent mandatory password-change security gate.\n2. The mandatory gate is not owned by the workspace/auth loading DOM, so workspace loading cannot make it disappear.\n3. Until a new password is saved, the user cannot continue into the application; only Sign out is available.\n4. Every signed-in account gets Profile → Security → Change password.\n5. Normal password change verifies the current password, requires a minimum of 8 characters and confirmation.\n6. Successful first-login change clears user_metadata.must_change_password and refreshes the session.\n7. PWA cache v76 / ${RELEASE}.\n`);
let release=read('tests/release-check.mjs');release+=`\ncheck(pkg.version==='17.7.1','package version is v17.7.1');\ncheck(index.includes('${RELEASE}'),'index cache token is v17.7.1');\ncheck(sw.includes('v76-${RELEASE}')&&sw.includes('account-security-v1771.js'),'service worker contains account security v17.7.1');\nconst accountSecurity=fs.readFileSync(path.join(root,'public/core/account-security-v1771.js'),'utf8');\ncheck(accountSecurity.includes('must_change_password')&&accountSecurity.includes('cat-password-required-v1771')&&accountSecurity.includes('Сменить пароль'),'account security includes mandatory temporary-password gate and profile password change');\ncheck(accountSecurity.includes('signInWithPassword')&&accountSecurity.includes('auth.updateUser')&&accountSecurity.includes('минимум 8 символов'),'password change verifies current password and updates Supabase Auth');\ncheck(performance.includes('loadAccountSecurity')&&performance.includes('account-security-v1771.js'),'performance loader installs account security');\n`;write('tests/release-check.mjs',release);
let spec=read('tests/app.spec.mjs');spec+=`\n\ntest('v17.7.1 temporary-password account gets persistent mandatory password gate', async ({ page }) => {\n await page.goto('/index.html',{waitUntil:'domcontentloaded'});\n await page.evaluate(()=>{\n window.CateriumAccountSecurityV1771=undefined;\n 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()=>({})}})};\n });\n const src=fs.readFileSync(path.join(process.cwd(),'public/core/account-security-v1771.js'),'utf8');await page.addScriptTag({content:src});\n await page.waitForSelector('#cateriumPasswordGateV1771');\n expect(await page.locator('#cateriumPasswordGateV1771').isVisible()).toBe(true);\n expect(await page.locator('#catPasswordCancelV1771').count()).toBe(0);\n await page.evaluate(()=>{document.body.insertAdjacentHTML('beforeend','<div id="workspace-loader-repaint"></div>')});\n await page.waitForTimeout(120);\n expect(await page.locator('#cateriumPasswordGateV1771').isVisible()).toBe(true);\n});\n\ntest('v17.7.1 every signed-in account gets Change password in Profile', async ({ page }) => {\n await page.goto('/index.html',{waitUntil:'domcontentloaded'});\n await page.evaluate(()=>{\n window.CateriumAccountSecurityV1771=undefined;\n document.body.insertAdjacentHTML('beforeend','<div id="sunCloudV2Card"><div class="sun-cloud-v2-box"><h3>Профиль</h3><div>user@example.com</div></div></div>');\n 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()=>({})}})};\n });\n const src=fs.readFileSync(path.join(process.cwd(),'public/core/account-security-v1771.js'),'utf8');await page.addScriptTag({content:src});\n await page.waitForSelector('#catProfilePasswordV1771');\n expect(await page.locator('#catProfilePasswordV1771').textContent()).toContain('Сменить пароль');\n await page.locator('#catProfilePasswordV1771').click();\n await expect(page.locator('#catCurrentPasswordV1771')).toBeVisible();\n});\n`;write('tests/app.spec.mjs',spec);
console.log('Applied Caterium v17.7.1 password-security release patch');