caterium-app/.github/scripts/patch-v1771-password-security.mjs
2026-09-08 16:36:47 +03:00

25 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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');