iobroker.eos-admin 7.9.34 → 7.9.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- const h="data:image/svg+xml,%3csvg%20height='512'%20viewBox='0%200%2064%2064'%20width='512'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='m61%202h-58c-.552%200-1%20.448-1%201v58c0%20.552.448%201%201%201h58c.552%200%201-.448%201-1v-58c0-.552-.448-1-1-1zm-1%206h-4v-2c0-.552-.448-1-1-1h-6c-.552%200-1%20.448-1%201v2h-3c-.552%200-1%20.448-1%201v9h-2v-14h18zm-12.142%2031-1.692-11h9.669l-1.692%2011zm1.142-13c0-1.103.897-2%202-2s2%20.897%202%202zm8.759.349c-.19-.222-.467-.349-.759-.349h-2c0-2.206-1.794-4-4-4s-4%201.794-4%204h-2c-.292%200-.569.127-.759.349s-.274.515-.229.803l1.823%2011.848h-3.835v-19h18v19h-3.835l1.823-11.848c.045-.288-.039-.582-.229-.803zm-7.759-17.349v-2h4v11h-4zm-2%209h-2v-8h2zm8%200v-8h4v8zm-16-14v14h-2v-10c0-.552-.448-1-1-1h-6c-.552%200-1%20.448-1%201v10h-2v-7c0-.265-.105-.52-.293-.707l-1.707-1.707v-2.586c0-.552-.448-1-1-1h-4c-.552%200-1%20.448-1%201v2.586l-1.707%201.707c-.188.187-.293.442-.293.707v7h-2v-10c0-.552-.448-1-1-1h-8c-.552%200-1%20.448-1%201v10h-2v-14zm-4%2014h-4v-9h4zm-11.707-8.293%201.707%201.707v6.586h-6v-6.586l1.707-1.707c.188-.187.293-.442.293-.707v-2h2v2c0%20.265.105.52.293.707zm-10.293%208.293h-6v-9h6zm-10%202h36v40h-36zm45%2028h-2v-1h2zm-3%202h4.649l4.351%203.48v6.52h-9zm11%2010v-7c0-.304-.138-.591-.375-.781l-5-4c-.178-.142-.398-.219-.625-.219v-2c0-.552-.448-1-1-1h-4c-.552%200-1%20.448-1%201v2c-.552%200-1%20.448-1%201v11h-2v-19h18v19z'/%3e%3cpath%20d='m37%2022h-30c-.552%200-1%20.448-1%201v34c0%20.552.448%201%201%201h30c.552%200%201-.448%201-1v-34c0-.552-.448-1-1-1zm-1%202v5h-28v-5zm-28%2032v-25h28v25z'/%3e%3cpath%20d='m22%2033c-6.065%200-11%204.935-11%2011s4.935%2011%2011%2011%2011-4.935%2011-11-4.935-11-11-11zm0%2020c-4.962%200-9-4.038-9-9s4.038-9%209-9%209%204.038%209%209-4.038%209-9%209z'/%3e%3cpath%20d='m26.199%2048.286%201.399%201.429c.677-.663%201.226-1.432%201.631-2.286l-1.807-.857c-.303.639-.714%201.216-1.223%201.714z'/%3e%3cpath%20d='m22%2036v2c3.309%200%206%202.691%206%206h2c0-4.411-3.589-8-8-8z'/%3e%3cpath%20d='m10%2025h2v2h-2z'/%3e%3cpath%20d='m14%2025h2v2h-2z'/%3e%3cpath%20d='m32%2025h2v2h-2z'/%3e%3c/g%3e%3c/svg%3e";export{h as default};
1
+ const h="data:image/svg+xml,%3csvg%20height='512'%20viewBox='0%200%2064%2064'%20width='512'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='m61%202h-58c-.552%200-1%20.448-1%201v58c0%20.552.448%201%201%201h58c.552%200%201-.448%201-1v-58c0-.552-.448-1-1-1zm-1%206h-4v-2c0-.552-.448-1-1-1h-6c-.552%200-1%20.448-1%201v2h-3c-.552%200-1%20.448-1%201v9h-2v-14h18zm-12.142%2031-1.692-11h9.669l-1.692%2011zm1.142-13c0-1.103.897-2%202-2s2%20.897%202%202zm8.759.349c-.19-.222-.467-.349-.759-.349h-2c0-2.206-1.794-4-4-4s-4%201.794-4%204h-2c-.292%200-.569.127-.759.349s-.274.515-.229.803l1.823%2011.848h-3.835v-19h18v19h-3.835l1.823-11.848c.045-.288-.039-.582-.229-.803zm-7.759-17.349v-2h4v11h-4zm-2%209h-2v-8h2zm8%200v-8h4v8zm-16-14v14h-2v-10c0-.552-.448-1-1-1h-6c-.552%200-1%20.448-1%201v10h-2v-7c0-.265-.105-.52-.293-.707l-1.707-1.707v-2.586c0-.552-.448-1-1-1h-4c-.552%200-1%20.448-1%201v2.586l-1.707%201.707c-.188.187-.293.442-.293.707v7h-2v-10c0-.552-.448-1-1-1h-8c-.552%200-1%20.448-1%201v10h-2v-14zm-4%2014h-4v-9h4zm-11.707-8.293%201.707%201.707v6.586h-6v-6.586l1.707-1.707c.188-.187.293-.442.293-.707v-2h2v2c0%20.265.105.52.293.707zm-10.293%208.293h-6v-9h6zm-10%202h36v40h-36zm45%2028h-2v-1h2zm-3%202h4.649l4.351%203.48v6.52h-9zm11%2010v-7c0-.304-.138-.591-.375-.781l-5-4c-.178-.142-.398-.219-.625-.219v-2c0-.552-.448-1-1-1h-4c-.552%200-1%20.448-1%201v2c-.552%200-1%20.448-1%201v11h-2v-19h18v19z'/%3e%3cpath%20d='m37%2022h-30c-.552%200-1%20.448-1%201v35c0%20.552.448%201%201%201h30c.552%200%201-.448%201-1v-34c0-.552-.448-1-1-1zm-1%202v5h-28v-5zm-28%2032v-25h28v25z'/%3e%3cpath%20d='m22%2033c-6.065%200-11%204.935-11%2011s4.935%2011%2011%2011%2011-4.935%2011-11-4.935-11-11-11zm0%2020c-4.962%200-9-4.038-9-9s4.038-9%209-9%209%204.038%209%209-4.038%209-9%209z'/%3e%3cpath%20d='m26.199%2048.286%201.399%201.429c.677-.663%201.226-1.432%201.631-2.286l-1.807-.857c-.303.639-.714%201.216-1.223%201.714z'/%3e%3cpath%20d='m22%2036v2c3.309%200%206%202.691%206%206h2c0-4.411-3.589-8-8-8z'/%3e%3cpath%20d='m10%2025h2v2h-2z'/%3e%3cpath%20d='m14%2025h2v2h-2z'/%3e%3cpath%20d='m32%2025h2v2h-2z'/%3e%3c/g%3e%3c/svg%3e";export{h as default};
@@ -1 +1 @@
1
- const c="data:image/svg+xml,%3csvg%20height='512'%20viewBox='0%200%2060%2060'%20width='512'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='m23%204h-15c-2.209139%200-4%201.790861-4%204v34c0%202.209139%201.790861%204%204%204h6c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-6c-1.1045695%200-2-.8954305-2-2v-34c0-1.1045695.8954305-2%202-2h15c1.1045695%200%202%20.8954305%202%202v12.05c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-12.05c0-2.209139-1.790861-4-4-4z'/%3e%3cpath%20d='m11%2012h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m11%2016h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m21%2019c0-.5522847-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201h9c.5522847%200%201-.4477153%201-1z'/%3e%3cpath%20d='m9%2035c-.55228475%200-1%20.4477153-1%201v5c0%20.5522847.44771525%201%201%201h3c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-2v-4c0-.5522847-.44771525-1-1-1z'/%3e%3cpath%20d='m52%200h-15c-2.9122142.00180691-5.5934008%201.58600518-7%204.136-1.4065992-2.54999482-4.0877858-4.13419309-7-4.136h-15c-4.41622192.00495988-7.99504012%203.58377808-8%208v34c.00495988%204.4162219%203.58377808%207.9950401%208%208h6c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-6c-3.31233757-.0033074-5.99669262-2.6876624-6-6v-34c.00330738-3.31233757%202.68766243-5.99669262%206-6h15c3.3123376.00330738%205.9966926%202.68766243%206%206v12c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-12c.0033074-3.31233757%202.6876624-5.99669262%206-6h15c3.3123376.00330738%205.9966926%202.68766243%206%206v34c-.0033074%203.3123376-2.6876624%205.9966926-6%206h-6c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201h6c4.4162219-.0049599%207.9950401-3.5837781%208-8v-34c-.0049599-4.41622192-3.5837781-7.99504012-8-8z'/%3e%3cpath%20d='m46%2046h6c2.209139%200%204-1.790861%204-4v-34c0-2.209139-1.790861-4-4-4h-15c-2.209139%200-4%201.790861-4%204v12.05c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-12.05c0-1.1045695.8954305-2%202-2h15c1.1045695%200%202%20.8954305%202%202v34c0%201.1045695-.8954305%202-2%202h-6c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m40%2012h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m40%2016h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m40%2020h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m49%2027v3c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-3c0-.5522847-.4477153-1-1-1s-1%20.4477153-1%201z'/%3e%3cpath%20d='m27%2023c-3.8641657.0044086-6.9955914%203.1358343-7%207v6c-1.6568542%200-3%201.3431458-3%203v18c0%201.6568542%201.3431458%203%203%203h20c1.6568542%200%203-1.3431458%203-3v-18c0-1.6568542-1.3431458-3-3-3v-6c-.0044086-3.8641657-3.1358343-6.9955914-7-7zm14%2016v18c0%20.5522847-.4477153%201-1%201h-20c-.5522847%200-1-.4477153-1-1v-18c0-.5522847.4477153-1%201-1h20c.5522847%200%201%20.4477153%201%201zm-7-3h-8v-6c0-.5522847.4477153-1%201-1h6c.5522847%200%201%20.4477153%201%201zm4-6v6h-2v-6c0-1.6568542-1.3431458-3-3-3h-6c-1.6568542%200-3%201.3431458-3%203v6h-2v-6c.0033061-2.7600532%202.2399468-4.9966939%205-5h6c2.7600532.0033061%204.9966939%202.2399468%205%205z'/%3e%3cpath%20d='m31.213%2041.144c-1.504172-.3693727-3.0946426-.0256068-4.312.932-1.2178834.9618134-1.9201275%202.4346089-1.9007403%203.9863657.0193871%201.5517568.7582076%203.0065481%201.9997403%203.9376343v3c0%201.6568542%201.3431458%203%203%203s3-1.3431458%203-3v-3c1.5445107-1.1569544%202.2853492-3.0994557%201.9035191-4.9910852-.3818301-1.8916296-1.8181587-3.3946643-3.6905191-3.8619148zm.587%207.256c-.4971479.3576066-.7942401.9306232-.8%201.543v3.057c0%20.5522847-.4477153%201-1%201s-1-.4477153-1-1v-3.081c-.0057082-.6020522-.2994259-1.1649492-.79-1.514-1.0350553-.7717872-1.4602164-2.1192507-1.0555364-3.3453131s1.548421-2.0556867%202.8395364-2.0596869c.2550309.0005085.5091144.0310522.757.091%201.055868.2632461%201.882907%201.0833772%202.155%202.137.3133746%201.1839695-.1244165%202.4395512-1.106%203.172z'/%3e%3c/g%3e%3c/svg%3e";export{c as default};
1
+ const c="data:image/svg+xml,%3csvg%20height='512'%20viewBox='0%200%2060%2060'%20width='512'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='m23%204h-15c-2.209139%200-4%201.790861-4%204v35c0%202.209139%201.790861%204%204%204h6c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-6c-1.1045695%200-2-.8954305-2-2v-34c0-1.1045695.8954305-2%202-2h15c1.1045695%200%202%20.8954305%202%202v12.05c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-12.05c0-2.209139-1.790861-4-4-4z'/%3e%3cpath%20d='m11%2012h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m11%2016h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m21%2019c0-.5522847-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201h9c.5522847%200%201-.4477153%201-1z'/%3e%3cpath%20d='m9%2035c-.55228475%200-1%20.4477153-1%201v5c0%20.5522847.44771525%201%201%201h3c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-2v-4c0-.5522847-.44771525-1-1-1z'/%3e%3cpath%20d='m52%200h-15c-2.9122142.00180691-5.5934008%201.58600518-7%204.136-1.4065992-2.54999482-4.0877858-4.13419309-7-4.136h-15c-4.41622192.00495988-7.99504012%203.58377808-8%208v35c.00495988%204.4162219%203.58377808%207.9950401%208%208h6c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-6c-3.31233757-.0033074-5.99669262-2.6876624-6-6v-34c.00330738-3.31233757%202.68766243-5.99669262%206-6h15c3.3123376.00330738%205.9966926%202.68766243%206%206v12c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-12c.0033074-3.31233757%202.6876624-5.99669262%206-6h15c3.3123376.00330738%205.9966926%202.68766243%206%206v35c-.0033074%203.3123376-2.6876624%205.9966926-6%206h-6c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201h6c4.4162219-.0049599%207.9950401-3.5837781%208-8v-34c-.0049599-4.41622192-3.5837781-7.99504012-8-8z'/%3e%3cpath%20d='m46%2046h6c2.209139%200%204-1.790861%204-4v-34c0-2.209139-1.790861-4-4-4h-15c-2.209139%200-4%201.790861-4%204v12.05c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-12.05c0-1.1045695.8954305-2%202-2h15c1.1045695%200%202%20.8954305%202%202v35c0%201.1045695-.8954305%202-2%202h-6c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m40%2012h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m40%2016h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m40%2020h9c.5522847%200%201-.4477153%201-1s-.4477153-1-1-1h-9c-.5522847%200-1%20.4477153-1%201s.4477153%201%201%201z'/%3e%3cpath%20d='m49%2027v3c0%20.5522847.4477153%201%201%201s1-.4477153%201-1v-3c0-.5522847-.4477153-1-1-1s-1%20.4477153-1%201z'/%3e%3cpath%20d='m27%2023c-3.8641657.0044086-6.9955914%203.1358343-7%207v6c-1.6568542%200-3%201.3431458-3%203v18c0%201.6568542%201.3431458%203%203%203h20c1.6568542%200%203-1.3431458%203-3v-18c0-1.6568542-1.3431458-3-3-3v-6c-.0044086-3.8641657-3.1358343-6.9955914-7-7zm14%2016v18c0%20.5522847-.4477153%201-1%201h-20c-.5522847%200-1-.4477153-1-1v-18c0-.5522847.4477153-1%201-1h20c.5522847%200%201%20.4477153%201%201zm-7-3h-8v-6c0-.5522847.4477153-1%201-1h6c.5522847%200%201%20.4477153%201%201zm4-6v6h-2v-6c0-1.6568542-1.3431458-3-3-3h-6c-1.6568542%200-3%201.3431458-3%203v6h-2v-6c.0033061-2.7600532%202.2399468-4.9966939%205-5h6c2.7600532.0033061%204.9966939%202.2399468%205%205z'/%3e%3cpath%20d='m31.213%2041.144c-1.504172-.3693727-3.0946426-.0256068-4.312.932-1.2178834.9618134-1.9201275%202.4346089-1.9007403%203.9863657.0193871%201.5517568.7582076%203.0065481%201.9997403%203.9376343v3c0%201.6568542%201.3431458%203%203%203s3-1.3431458%203-3v-3c1.5445107-1.1569544%202.2853492-3.0994557%201.9035191-4.9910852-.3818301-1.8916296-1.8181587-3.3946643-3.6905191-3.8619148zm.587%207.256c-.4971479.3576066-.7942401.9306232-.8%201.543v3.057c0%20.5522847-.4477153%201-1%201s-1-.4477153-1-1v-3.081c-.0057082-.6020522-.2994259-1.1649492-.79-1.514-1.0350553-.7717872-1.4602164-2.1192507-1.0555364-3.3453131s1.548421-2.0556867%202.8395364-2.0596869c.2550309.0005085.5091144.0310522.757.091%201.055868.2632461%201.882907%201.0833772%202.155%202.137.3133746%201.1839695-.1244165%202.4395512-1.106%203.172z'/%3e%3c/g%3e%3c/svg%3e";export{c as default};
@@ -1 +1 @@
1
- const c="data:image/svg+xml,%3csvg%20height='512'%20viewBox='0%200%20512%20512'%20width='512'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='m510.417%20233.225-58.644-117.279c-15.939-31.877-47.978-51.68-83.62-51.68-8.586%200-16.984%201.188-25.032%203.437.105-1.489.178-2.988.178-4.503%200-34.849-28.351-63.2-63.2-63.2s-63.2%2028.352-63.2%2063.2c0%2030.993%2022.432%2056.828%2051.909%2062.169l-61.366%2061.47c-6.875%206.886-21.871%2027.82-10.333%2054.46-1.705-.191-3.421-.299-5.144-.299-23.087%200-42.336%2016.69-46.351%2038.635-7.74-4.144-16.573-6.501-25.949-6.501-30.419%200-55.167%2024.748-55.167%2055.167%200%209.063%202.211%2017.615%206.1%2025.167h-40.598v-338.468c0-8.284-6.716-15-15-15s-15%206.716-15%2015v482c0%208.284%206.716%2015%2015%2015s15-6.716%2015-15v-49.267h306.563c8.284%200%2015-6.716%2015-15v-64.267c0-8.284-6.716-15-15-15h-36.412c3.274-8.395%203.214-15.263%203.214-18.2%2028.469%200%2048.2-22.098%2048.2-47.133%200-25.989-21.144-47.133-47.133-47.133h-12.304l55.904-56.086%2053.736%20106.777-.103%20205.301c-.002%203.979%201.578%207.796%204.391%2010.611%202.813%202.814%206.63%204.396%2010.609%204.396h80.335c8.284%200%2015-6.716%2015-15v-257.066c0-2.329-.542-4.625-1.583-6.708zm-263.517-170.025c0-18.307%2014.894-33.2%2033.2-33.2s33.2%2014.894%2033.2%2033.2-14.894%2033.2-33.2%2033.2c-18.307%200-33.2-14.893-33.2-33.2zm-127.233%20239.933c13.877%200%2025.167%2011.29%2025.167%2025.167s-11.29%2025.167-25.167%2025.167-25.167-11.29-25.167-25.167%2011.29-25.167%2025.167-25.167zm201.896%2080.334v34.267h-291.563v-34.267zm-17.13-112.467c9.447%200%2017.133%207.686%2017.133%2017.133%200%209.583-7.814%2017.133-17.133%2017.133h-16.067c-8.284%200-15%206.716-15%2015v16.067c0%209.583-7.814%2017.133-17.133%2017.133h-64.267c-9.447%200-17.133-7.686-17.133-17.133v-48.2c0-9.447%207.686-17.133%2017.133-17.133%209.297%200%2017.133%207.526%2017.133%2017.133v16.067c0%208.284%206.716%2015%2015%2015s15-6.716%2015-15v-16.067c0-9.429%207.616-17.133%2017.133-17.133zm177.567%20211h-50.326l.097-193.859c.001-2.344-.547-4.656-1.601-6.75l-64.685-128.533c-2.167-4.305-6.269-7.306-11.027-8.068-4.761-.762-9.594.81-12.995%204.222l-86.458%2086.739c-7.263%207.291-19.115%206.807-26.308-.386-7.381-7.381-7.728-19.611-.022-27.329l95.27-95.431c11.799-11.825%2027.5-18.337%2044.217-18.337%2024.199%200%2045.955%2013.448%2056.779%2035.097l57.059%20114.109z'/%3e%3c/g%3e%3c/svg%3e";export{c as default};
1
+ const c="data:image/svg+xml,%3csvg%20height='512'%20viewBox='0%200%20512%20512'%20width='512'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='m510.417%20233.225-58.644-117.279c-15.939-31.877-47.978-51.68-83.62-51.68-8.586%200-16.984%201.188-25.032%203.437.105-1.489.178-2.988.178-4.503%200-34.849-28.351-63.2-63.2-63.2s-63.2%2028.352-63.2%2063.2c0%2030.993%2022.432%2056.828%2051.909%2062.169l-61.366%2061.47c-6.875%206.886-21.871%2027.82-10.333%2054.46-1.705-.191-3.421-.299-5.144-.299-23.087%200-42.336%2016.69-46.351%2038.635-7.74-4.144-16.573-6.501-25.949-6.501-30.419%200-55.167%2024.748-55.167%2055.167%200%209.063%202.211%2017.615%206.1%2025.167h-40.598v-338.468c0-8.284-6.716-15-15-15s-15%206.716-15%2015v482c0%208.284%206.716%2015%2015%2015s15-6.716%2015-15v-49.267h306.563c8.284%200%2015-6.716%2015-15v-64.267c0-8.284-6.716-15-15-15h-36.412c3.274-8.395%203.214-15.263%203.214-18.2%2028.469%200%2048.2-22.098%2048.2-47.133%200-25.989-21.144-47.133-47.133-47.133h-12.304l55.904-56.086%2053.736%20106.777-.103%20205.301c-.002%203.979%201.578%207.796%204.391%2010.611%202.813%202.814%206.63%204.396%2010.609%204.396h80.335c8.284%200%2015-6.716%2015-15v-257.066c0-2.329-.542-4.625-1.583-6.708zm-263.517-170.025c0-18.307%2014.894-33.2%2033.2-33.2s33.2%2014.894%2033.2%2033.2-14.894%2033.2-33.2%2033.2c-18.307%200-33.2-14.893-33.2-33.2zm-127.233%20239.933c13.877%200%2025.167%2011.29%2025.167%2025.167s-11.29%2025.167-25.167%2025.167-25.167-11.29-25.167-25.167%2011.29-25.167%2025.167-25.167zm201.896%2080.334v35.267h-291.563v-34.267zm-17.13-112.467c9.447%200%2017.133%207.686%2017.133%2017.133%200%209.583-7.814%2017.133-17.133%2017.133h-16.067c-8.284%200-15%206.716-15%2015v16.067c0%209.583-7.814%2017.133-17.133%2017.133h-64.267c-9.447%200-17.133-7.686-17.133-17.133v-48.2c0-9.447%207.686-17.133%2017.133-17.133%209.297%200%2017.133%207.526%2017.133%2017.133v16.067c0%208.284%206.716%2015%2015%2015s15-6.716%2015-15v-16.067c0-9.429%207.616-17.133%2017.133-17.133zm177.567%20211h-50.326l.097-193.859c.001-2.344-.547-4.656-1.601-6.75l-64.685-128.533c-2.167-4.305-6.269-7.306-11.027-8.068-4.761-.762-9.594.81-12.995%204.222l-86.458%2086.739c-7.263%207.291-19.115%206.807-26.308-.386-7.381-7.381-7.728-19.611-.022-27.329l95.27-95.431c11.799-11.825%2027.5-18.337%2044.217-18.337%2024.199%200%2045.955%2013.448%2056.779%2035.097l57.059%20114.109z'/%3e%3c/g%3e%3c/svg%3e";export{c as default};
@@ -1 +1 @@
1
- const c="data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20480%20480'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='M456,224c-14.133,0-24,6.301-24,15.32v27.505C419.333,241.793,399.85,224,376,224H152c-4.417-0.001-7.999,3.579-8,7.996%20c0,0.001,0,0.003,0,0.004v48.067c0.045-13.052-5.201-26.075-15.586-35.583c-19.552-17.902-49.915-16.564-67.816,2.989%20c-16.764,18.309-16.801,46.38-0.086,64.734c-4.612,0.508-8.968,2.38-12.512,5.375V115.199C48,104.434,37.461,96,24,96%20s-24,8.434-24,19.199v345.602C0,471.566,10.539,480,24,480s24-8.434,24-19.199V408h384v56.68c0,9.019,9.867,15.32,24,15.32%20s24-6.301,24-15.32V239.32C480,230.301,470.133,224,456,224z%20M32,460.801c-0.086,0.656-2.773,3.199-8,3.199%20c-5.25,0-7.922-2.543-8-3.199V115.199c0.078-0.656,2.75-3.199,8-3.199c5.227,0,7.914,2.543,8,3.199V460.801z%20M160,240h216%20c30.172,0,53.172,44.926,55.758,88H160V240z%20M144,280.083v38.56c-3.452-3.353-7.848-5.566-12.597-6.342%20C139.793,303.137,143.956,291.6,144,280.083z%20M96,248c17.673,0,32,14.327,32,32c0,17.673-14.327,32-32,32s-32-14.327-32-32%20C64.019,262.335,78.335,248.019,96,248z%20M432,392H48v-48.023c4.163-0.328,7.374-3.801,7.375-7.977%20c-0.077-4.331,3.364-7.909,7.695-8h64.61c4.331,0.091,7.772,3.669,7.695,8c-0.001,4.417,3.579,7.999,7.996,8%20c0.001,0,0.003,0,0.004,0H432V392z%20M464,462.594c-5.169,1.875-10.831,1.875-16,0V241.406c5.169-1.875,10.831-1.875,16,0V462.594z'%20/%3e%3cpath%20d='M137.078,176l29.07-34.879c1.986-2.386,2.413-5.705,1.094-8.516c-1.316-2.81-4.139-4.605-7.242-4.605h-48v16h30.922%20l-29.07,34.879c-2.827,3.398-2.364,8.444,1.034,11.27c1.437,1.195,3.246,1.85,5.114,1.851h48v-16H137.078z'/%3e%3cpath%20d='M224.359,136l45.953-59.09c1.877-2.411,2.217-5.681,0.875-8.426c-1.344-2.743-4.132-4.483-7.188-4.484h-64v16h47.641%20l-45.953,59.09c-2.714,3.484-2.089,8.509,1.396,11.223c1.405,1.094,3.136,1.688,4.917,1.688h64v-16H224.359z'/%3e%3cpath%20d='M328,96l62.398-83.199c2.652-3.533,1.939-8.546-1.594-11.199C387.419,0.562,385.733,0,384,0h-72v16h56l-62.398,83.199%20c-1.818,2.424-2.112,5.668-0.758,8.379C306.2,110.288,308.97,112,312,112h80V96H328z'/%3e%3c/g%3e%3c/svg%3e";export{c as default};
1
+ const c="data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20480%20480'%3e%3cg%20fill='currentColor'%3e%3cpath%20d='M456,224c-14.133,0-24,6.301-24,15.32v27.505C419.333,241.793,399.85,224,376,224H152c-4.417-0.001-7.999,3.579-8,7.996%20c0,0.001,0,0.003,0,0.004v48.067c0.045-13.052-5.201-26.075-15.586-35.583c-19.552-17.902-49.915-16.564-67.816,2.989%20c-16.764,18.309-16.801,46.38-0.086,64.734c-4.612,0.508-8.968,2.38-12.512,5.375V115.199C48,104.434,37.461,96,24,96%20s-24,8.434-24,19.199v355.602C0,471.566,10.539,480,24,480s24-8.434,24-19.199V408h384v56.68c0,9.019,9.867,15.32,24,15.32%20s24-6.301,24-15.32V239.32C480,230.301,470.133,224,456,224z%20M32,460.801c-0.086,0.656-2.773,3.199-8,3.199%20c-5.25,0-7.922-2.543-8-3.199V115.199c0.078-0.656,2.75-3.199,8-3.199c5.227,0,7.914,2.543,8,3.199V460.801z%20M160,240h216%20c30.172,0,53.172,44.926,55.758,88H160V240z%20M144,280.083v38.56c-3.452-3.353-7.848-5.566-12.597-6.342%20C139.793,303.137,143.956,291.6,144,280.083z%20M96,248c17.673,0,32,14.327,32,32c0,17.673-14.327,32-32,32s-32-14.327-32-32%20C64.019,262.335,78.335,248.019,96,248z%20M432,392H48v-48.023c4.163-0.328,7.374-3.801,7.375-7.977%20c-0.077-4.331,3.364-7.909,7.695-8h64.61c4.331,0.091,7.772,3.669,7.695,8c-0.001,4.417,3.579,7.999,7.996,8%20c0.001,0,0.003,0,0.004,0H432V392z%20M464,462.594c-5.169,1.875-10.831,1.875-16,0V241.406c5.169-1.875,10.831-1.875,16,0V462.594z'%20/%3e%3cpath%20d='M137.078,176l29.07-34.879c1.986-2.386,2.413-5.705,1.094-8.516c-1.316-2.81-4.139-4.605-7.242-4.605h-48v16h30.922%20l-29.07,34.879c-2.827,3.398-2.364,8.444,1.034,11.27c1.437,1.195,3.246,1.85,5.114,1.851h48v-16H137.078z'/%3e%3cpath%20d='M224.359,136l45.953-59.09c1.877-2.411,2.217-5.681,0.875-8.426c-1.344-2.743-4.132-4.483-7.188-4.484h-64v16h47.641%20l-45.953,59.09c-2.714,3.484-2.089,8.509,1.396,11.223c1.405,1.094,3.136,1.688,4.917,1.688h64v-16H224.359z'/%3e%3cpath%20d='M328,96l62.398-83.199c2.652-3.533,1.939-8.546-1.594-11.199C387.419,0.562,385.733,0,384,0h-72v16h56l-62.398,83.199%20c-1.818,2.424-2.112,5.668-0.758,8.379C306.2,110.288,308.97,112,312,112h80V96H328z'/%3e%3c/g%3e%3c/svg%3e";export{c as default};
@@ -3287,3 +3287,87 @@ html.eos-app button[class*="fab"] {
3287
3287
  display: none !important;
3288
3288
  }
3289
3289
  }
3290
+
3291
+
3292
+ /* === NexoWatt EOS v35: login redirect + adapter config interaction fix ======
3293
+ Keep native adapter configuration pages fully clickable and reserve the bottom
3294
+ right corner for adapter/page floating actions. */
3295
+ html.eos-app.eos-adapter-config-surface #app-paper button,
3296
+ html.eos-app.eos-adapter-config-surface #app-paper [role="button"],
3297
+ html.eos-app.eos-adapter-config-surface #app-paper a,
3298
+ html.eos-app.eos-adapter-config-surface #app-paper input,
3299
+ html.eos-app.eos-adapter-config-surface #app-paper select,
3300
+ html.eos-app.eos-adapter-config-surface #app-paper textarea {
3301
+ pointer-events: auto !important;
3302
+ }
3303
+ html.eos-app.eos-adapter-config-surface #app-paper .MuiButton-root,
3304
+ html.eos-app.eos-adapter-config-surface #app-paper .MuiIconButton-root,
3305
+ html.eos-app.eos-adapter-config-surface #app-paper .MuiMenuItem-root {
3306
+ position: relative !important;
3307
+ z-index: 12 !important;
3308
+ }
3309
+ html.eos-app .eos-assist-root,
3310
+ html.eos-app #eos-assist-root {
3311
+ right: 150px !important;
3312
+ bottom: 22px !important;
3313
+ }
3314
+ @media (max-width: 1100px) {
3315
+ html.eos-app .eos-assist-root,
3316
+ html.eos-app #eos-assist-root { right: 126px !important; }
3317
+ }
3318
+ @media (max-width: 720px) {
3319
+ html.eos-app .eos-assist-root,
3320
+ html.eos-app #eos-assist-root { right: 96px !important; }
3321
+ }
3322
+
3323
+
3324
+ /* === NexoWatt EOS v36: native adapter configuration safe mode =============
3325
+ Custom adapter configuration pages (React/HTML/jsonConfig) must be fully
3326
+ controlled by the adapter itself. EOS shell decoration is disabled inside the
3327
+ content area so buttons such as "Gerät hinzufügen" and "Gerät bearbeiten" stay
3328
+ clickable and dialogs/popovers are not hidden behind overlays. */
3329
+ html.eos-app.eos-adapter-config-surface #app-paper,
3330
+ html.eos-app.eos-adapter-config-surface #app-paper * {
3331
+ pointer-events: auto !important;
3332
+ }
3333
+ html.eos-app.eos-adapter-config-surface #app-paper button,
3334
+ html.eos-app.eos-adapter-config-surface #app-paper [role="button"],
3335
+ html.eos-app.eos-adapter-config-surface #app-paper a,
3336
+ html.eos-app.eos-adapter-config-surface #app-paper input,
3337
+ html.eos-app.eos-adapter-config-surface #app-paper select,
3338
+ html.eos-app.eos-adapter-config-surface #app-paper textarea,
3339
+ html.eos-app.eos-adapter-config-surface #app-paper .MuiButton-root,
3340
+ html.eos-app.eos-adapter-config-surface #app-paper .MuiIconButton-root,
3341
+ html.eos-app.eos-adapter-config-surface #app-paper .MuiMenuItem-root {
3342
+ pointer-events: auto !important;
3343
+ user-select: auto !important;
3344
+ }
3345
+ html.eos-app.eos-adapter-config-surface .eos-assist-root,
3346
+ html.eos-app.eos-adapter-config-surface #eos-assist-root,
3347
+ html.eos-app.eos-adapter-config-surface .eos-assist-config-hidden {
3348
+ display: none !important;
3349
+ visibility: hidden !important;
3350
+ pointer-events: none !important;
3351
+ }
3352
+ html.eos-app.eos-adapter-config-surface .MuiDialog-root,
3353
+ html.eos-app.eos-adapter-config-surface .MuiModal-root,
3354
+ html.eos-app.eos-adapter-config-surface .MuiPopover-root,
3355
+ html.eos-app.eos-adapter-config-surface .MuiMenu-root,
3356
+ html.eos-app.eos-adapter-config-surface .MuiDialog-container {
3357
+ pointer-events: auto !important;
3358
+ z-index: 4200 !important;
3359
+ }
3360
+ html.eos-app.eos-adapter-config-surface .MuiDialog-paper,
3361
+ html.eos-app.eos-adapter-config-surface .MuiPopover-paper,
3362
+ html.eos-app.eos-adapter-config-surface .MuiMenu-paper {
3363
+ pointer-events: auto !important;
3364
+ }
3365
+ html.eos-app.eos-adapter-config-surface #app-paper .eos-protected-delete-control,
3366
+ html.eos-app.eos-adapter-config-surface #app-paper .eos-security-hidden-delete,
3367
+ html.eos-app.eos-adapter-config-surface #app-paper .eos-protected-adapter-row {
3368
+ display: revert !important;
3369
+ visibility: visible !important;
3370
+ opacity: 1 !important;
3371
+ filter: none !important;
3372
+ pointer-events: auto !important;
3373
+ }
@@ -31,7 +31,7 @@
31
31
  rel="stylesheet"
32
32
  href="css/leaflet.css"
33
33
  />
34
- <link rel="stylesheet" href="./css/eos-branding.css?v=34" />
34
+ <link rel="stylesheet" href="./css/eos-branding.css?v=36" />
35
35
  <link
36
36
  rel="manifest"
37
37
  href="manifest.json"
@@ -154,10 +154,9 @@
154
154
  <script type="module" crossorigin src="./assets/index-CQZugZ1z.js"></script>
155
155
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
156
156
  <link rel="modulepreload" crossorigin href="./assets/iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js">
157
- <script defer src="./js/eos-branding.js?v=34"></script>
158
- <script defer src="./js/eos-security-ui.js?v=34"></script>
159
- <script defer src="./js/eos-hard-logout.js?v=34"></script>
160
- <script defer src="./js/eos-assistant.js?v=34"></script>
157
+ <script defer src="./js/eos-branding.js?v=36"></script>
158
+ <script defer src="./js/eos-security-ui.js?v=36"></script>
159
+ <script defer src="./js/eos-assistant.js?v=36"></script>
161
160
  </head>
162
161
  <body>
163
162
  <noscript>You need to enable JavaScript to run this app.</noscript>
@@ -2,5 +2,5 @@
2
2
  'use strict';
3
3
  // v31: EOS Assist is rendered by eos-branding.js so it can share route/security state.
4
4
  // This file stays as a lightweight compatibility hook for cache-safe deployments.
5
- window.NEXOWATT_EOS_ASSIST_VERSION = 'v33-assist-position-fix';
5
+ window.NEXOWATT_EOS_ASSIST_VERSION = 'v35-login-config-fix';
6
6
  })();
@@ -1,7 +1,7 @@
1
1
  (() => {
2
2
  'use strict';
3
3
 
4
- window.NEXOWATT_EOS_UI_VERSION = 'v33-assist-position-fix';
4
+ window.NEXOWATT_EOS_UI_VERSION = 'v36-native-config-session-fix';
5
5
 
6
6
  const BRAND = 'NexoWatt EOS';
7
7
  const EOS_MEANING = 'Energy Operation System';
@@ -398,6 +398,9 @@
398
398
  const applySecurityUiGuard = () => safe(() => {
399
399
  const policy = state.securityPolicy;
400
400
  applySecurityClasses();
401
+ // Do not apply EOS security decoration inside native adapter configuration pages.
402
+ // Adapter UIs must remain 100% functional; backend/role checks still protect EOS actions.
403
+ if (isAdapterConfigSurface()) return;
401
404
  if (!policy.loaded) return;
402
405
  if (isAdminUser()) {
403
406
  document.querySelectorAll('.eos-hidden-legacy-admin, .eos-protected-adapter-row').forEach(el => {
@@ -448,12 +451,16 @@
448
451
  });
449
452
 
450
453
  const normalizeBadAddressAfterLogin = () => safe(() => {
451
- if (!document.getElementById('app-paper')) return;
452
454
  const pathname = window.location.pathname || '';
453
- if (/(?:\/login|\/logout|\/404\.html)$/i.test(pathname)) {
454
- const clean = new URL(ASSET_BASE);
455
- clean.hash = window.location.hash || '#/tab-intro';
455
+ const badPath = /(?:%2f%23|%252f%2523|\/login|\/logout|\/404(?:\.html)?)/i.test(pathname)
456
+ || /(?:^|[?&])(?:hard|origin)=/i.test(window.location.search || '');
457
+ if (!badPath) return;
458
+ const clean = new URL(ASSET_BASE);
459
+ clean.hash = window.location.hash && !/%23|hard=|login/i.test(window.location.hash) ? window.location.hash : '#/tab-intro';
460
+ if (document.getElementById('app-paper')) {
456
461
  window.history.replaceState(null, document.title, `${clean.pathname}${clean.search}${clean.hash}`);
462
+ } else if (/(?:%2f%23|%252f%2523)/i.test(pathname)) {
463
+ window.location.replace(`${clean.pathname}${clean.search}#/tab-intro`);
457
464
  }
458
465
  });
459
466
 
@@ -465,6 +472,37 @@
465
472
  document.documentElement.classList.toggle('eos-route-intro', routes.intro);
466
473
  };
467
474
 
475
+
476
+ const isAdapterConfigSurface = () => document.documentElement.classList.contains('eos-adapter-config-surface');
477
+
478
+ const markAdapterConfigSurface = () => safe(() => {
479
+ const app = document.querySelector('#app-paper') || document.body;
480
+ const text = textOfElement(app).slice(0, 3500);
481
+ const isConfig = /Instanzeinstellungen:|Instance settings:|Gerät hinzufügen|Gerät bearbeiten|Geräteliste|Adapterkonfiguration|json exportieren|json importieren|Speichern und schließen|Save and close/i.test(text);
482
+ document.documentElement.classList.toggle('eos-adapter-config-surface', !!isConfig);
483
+ if (!isConfig) return;
484
+
485
+ // Native adapter configuration UIs are owned by the adapter. EOS must never
486
+ // block, rewrite or intercept their controls. This is critical for custom
487
+ // React/HTML configuration pages such as nexowatt-devices.
488
+ document.querySelectorAll('#app-paper button, #app-paper [role="button"], #app-paper a, #app-paper input, #app-paper select, #app-paper textarea, #app-paper [tabindex]').forEach(control => {
489
+ if (control.closest('.eos-assist-root, #eos-assist-root, .eos-standalone-nav-toggle')) return;
490
+ control.style.pointerEvents = 'auto';
491
+ control.removeAttribute('aria-disabled');
492
+ });
493
+ document.querySelectorAll('#app-paper .eos-protected-delete-control, #app-paper .eos-security-hidden-delete, #app-paper .eos-protected-adapter-row').forEach(el => {
494
+ el.classList.remove('eos-protected-delete-control', 'eos-security-hidden-delete', 'eos-protected-adapter-row');
495
+ el.removeAttribute('aria-disabled');
496
+ if (el.style) {
497
+ el.style.pointerEvents = '';
498
+ el.style.display = '';
499
+ el.style.visibility = '';
500
+ el.style.opacity = '';
501
+ }
502
+ if ('disabled' in el && !el.dataset.eosOriginalDisabled) el.disabled = false;
503
+ });
504
+ });
505
+
468
506
  const getLoginCard = () => {
469
507
  const input = document.querySelector('#username, input[name="username"], #password, input[type="password"]');
470
508
  return input ? input.closest('.MuiPaper-root, form, main > div') : null;
@@ -533,9 +571,10 @@
533
571
 
534
572
  const hardLogout = () => {
535
573
  clearAuthStorage();
536
- const loginUrl = new URL('index.html?login', ASSET_BASE);
537
- loginUrl.searchParams.set('eosLogout', 'timeout');
538
- window.location.replace(loginUrl.href);
574
+ const logoutUrl = new URL('logout', window.location.origin + '/');
575
+ logoutUrl.searchParams.set('hard', '1');
576
+ logoutUrl.searchParams.set('ts', String(Date.now()));
577
+ window.location.replace(logoutUrl.href);
539
578
  };
540
579
 
541
580
  const scheduleHardLogoutCheck = delay => {
@@ -573,13 +612,10 @@
573
612
  }
574
613
 
575
614
  const installHardLogoutWatchdog = () => {
576
- if (hardLogoutInstalled) return;
615
+ // v36: disabled. Upstream ioBroker Admin session handling is used again so
616
+ // the configured admin TTL is respected and native adapter config pages are
617
+ // not interrupted by duplicate EOS timers.
577
618
  hardLogoutInstalled = true;
578
- window.addEventListener('focus', () => checkHardLogoutSession(), { passive: true });
579
- document.addEventListener('visibilitychange', () => {
580
- if (!document.hidden) checkHardLogoutSession();
581
- }, { passive: true });
582
- scheduleHardLogoutCheck(2500);
583
619
  };
584
620
 
585
621
  const ensureBrandBadge = toolbar => {
@@ -990,6 +1026,11 @@
990
1026
  document.querySelectorAll('.eos-assist-launcher,.eos-assist-panel:not(#eos-assist-root .eos-assist-panel)').forEach(el => el.remove());
991
1027
  return;
992
1028
  }
1029
+ if (isAdapterConfigSurface()) {
1030
+ const existing = document.getElementById('eos-assist-root');
1031
+ if (existing) existing.classList.add('eos-assist-config-hidden');
1032
+ return;
1033
+ }
993
1034
 
994
1035
  let root = document.getElementById('eos-assist-root');
995
1036
  if (!root) {
@@ -1023,6 +1064,7 @@
1023
1064
  document.body.appendChild(root);
1024
1065
  }
1025
1066
 
1067
+ root.classList.remove('eos-assist-config-hidden');
1026
1068
  const ctx = assistContext();
1027
1069
  const button = root.querySelector('.eos-assist-button');
1028
1070
  const input = root.querySelector('.eos-assist-input');
@@ -1172,6 +1214,7 @@
1172
1214
  patchDocumentMeta();
1173
1215
  patchLogin();
1174
1216
  patchShell();
1217
+ markAdapterConfigSurface();
1175
1218
  applyNavCompactPreference();
1176
1219
  ensureStandaloneNavToggle();
1177
1220
  installAssistDelegatedClick();
@@ -1183,8 +1226,17 @@
1183
1226
  hideNativeLogoutNav();
1184
1227
  hideOfficialNexoWattRepoWarning();
1185
1228
  applySecurityUiGuard();
1186
- patchTextNodes(document.body || document.documentElement);
1187
- patchAttributes(document.body || document.documentElement);
1229
+ if (isAdapterConfigSurface()) {
1230
+ ['.MuiAppBar-root', '.MuiDrawer-paper', 'nav', '.eos-brand-badge', '.eos-top-toolbar'].forEach(selector => {
1231
+ document.querySelectorAll(selector).forEach(scope => {
1232
+ patchTextNodes(scope);
1233
+ patchAttributes(scope);
1234
+ });
1235
+ });
1236
+ } else {
1237
+ patchTextNodes(document.body || document.documentElement);
1238
+ patchAttributes(document.body || document.documentElement);
1239
+ }
1188
1240
  };
1189
1241
 
1190
1242
  const scopePatch = () => {
@@ -1194,6 +1246,7 @@
1194
1246
  normalizeBadAddressAfterLogin();
1195
1247
  patchLogin();
1196
1248
  patchShell();
1249
+ markAdapterConfigSurface();
1197
1250
  applyNavCompactPreference();
1198
1251
  ensureStandaloneNavToggle();
1199
1252
  installAssistDelegatedClick();
@@ -1207,6 +1260,7 @@
1207
1260
  applySecurityUiGuard();
1208
1261
  for (const scope of scopes.slice(0, 80)) {
1209
1262
  if (!scope || !scope.isConnected) continue;
1263
+ if (isAdapterConfigSurface() && (scope.id === 'app-paper' || scope.closest?.('#app-paper'))) continue;
1210
1264
  patchTextNodes(scope);
1211
1265
  patchAttributes(scope);
1212
1266
  }
@@ -1,163 +1,18 @@
1
1
  (function () {
2
2
  'use strict';
3
-
4
- const LOG_PREFIX = '[NexoWatt EOS hard logout]';
5
- const VERSION = '34';
6
- const MIN_POLL_MS = 15_000;
7
- const MAX_TIMER_MS = 2_147_000_000;
8
- const MIN_TTL_SEC = 5;
9
- const STORAGE_KEY = `nexowatt:eos:hardLogoutAt:${location.host}:${location.pathname.split('/')[1] || 'root'}`;
10
- let logoutTimer = null;
11
- let pollTimer = null;
12
- let logoutStarted = false;
13
-
14
- function isLoginPage() {
15
- const path = String(window.location.pathname || '').toLowerCase();
16
- const search = String(window.location.search || '').toLowerCase();
17
- return path.endsWith('/login') || path.includes('/login/') || search.includes('login');
18
- }
19
-
20
- function clearStoredTokens() {
21
- const storages = [window.localStorage, window.sessionStorage, window._localStorage, window._sessionStorage]
22
- .filter(Boolean)
23
- .filter((storage, index, array) => array.indexOf(storage) === index);
24
- const tokenKeyPattern = /(access[_-]?token|refresh[_-]?token|token[_-]?expires|expires[_-]?in|oauth|bearer|auth|connection)/i;
25
- for (const storage of storages) {
26
- try {
27
- const keys = [];
28
- for (let i = 0; i < storage.length; i++) {
29
- const key = storage.key(i);
30
- if (key && (tokenKeyPattern.test(key) || key === STORAGE_KEY)) {
31
- keys.push(key);
32
- }
33
- }
34
- keys.forEach(key => storage.removeItem(key));
35
- } catch (e) {
36
- // ignore blocked storage
37
- }
38
- }
39
- }
40
-
41
- function clearAuthCookies() {
42
- const cookieNames = ['access_token', 'refresh_token', 'connect.sid', 'ioBroker.sid'];
43
- const paths = ['/', window.location.pathname.replace(/\/[^/]*$/, '/') || '/'];
44
- for (const name of cookieNames) {
45
- for (const path of paths) {
46
- document.cookie = `${name}=; Max-Age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}; SameSite=Lax`;
47
- }
48
- }
49
- }
50
-
51
- function readDeadline() {
52
- try {
53
- const value = Number(window.localStorage.getItem(STORAGE_KEY));
54
- return Number.isFinite(value) && value > 0 ? value : 0;
55
- } catch (e) {
56
- return 0;
57
- }
58
- }
59
-
60
- function writeDeadline(deadline) {
61
- try {
62
- window.localStorage.setItem(STORAGE_KEY, String(deadline));
63
- } catch (e) {
64
- // ignore blocked storage
65
- }
66
- }
67
-
68
- function hardLogout(reason) {
69
- if (logoutStarted || isLoginPage()) return;
70
- logoutStarted = true;
71
- try { console.warn(LOG_PREFIX, reason || 'session expired'); } catch (e) {}
72
- if (logoutTimer) {
73
- clearTimeout(logoutTimer);
74
- logoutTimer = null;
75
- }
76
- if (pollTimer) {
77
- clearInterval(pollTimer);
78
- pollTimer = null;
79
- }
80
- clearStoredTokens();
81
- clearAuthCookies();
82
- const origin = encodeURIComponent((window.location.pathname || '/') + (window.location.search || '') + (window.location.hash || ''));
83
- window.location.href = './logout?origin=' + origin + '&hard=1';
84
- }
85
-
86
- function scheduleHardLogout(deadline) {
87
- const ms = Math.min(Math.max(deadline - Date.now() + 250, 250), MAX_TIMER_MS);
88
- if (logoutTimer) clearTimeout(logoutTimer);
89
- logoutTimer = setTimeout(() => hardLogout('configured login timeout reached'), ms);
90
- }
91
-
92
- function applyServerExpiration(expireInSec) {
93
- const seconds = Number(expireInSec);
94
- if (!Number.isFinite(seconds)) return;
95
- if (seconds <= 0) {
96
- hardLogout('server reported expired session');
97
- return;
98
- }
99
- if (seconds < MIN_TTL_SEC) return;
100
-
101
- const now = Date.now();
102
- const candidateDeadline = now + seconds * 1000;
103
- const storedDeadline = readDeadline();
104
-
105
- // Set the hard deadline once. If the server reports an earlier expiration later,
106
- // tighten the deadline. Never extend it through refresh-token based renewal.
107
- const deadline = !storedDeadline || candidateDeadline < storedDeadline - 5000 ? candidateDeadline : storedDeadline;
108
- if (deadline !== storedDeadline) writeDeadline(deadline);
109
-
110
- if (now >= deadline) {
111
- hardLogout('stored hard deadline reached');
112
- } else {
113
- scheduleHardLogout(deadline);
114
- }
115
- }
116
-
117
- async function checkSession() {
118
- if (logoutStarted) return;
119
- if (isLoginPage()) {
120
- clearStoredTokens();
121
- clearAuthCookies();
122
- return;
123
- }
124
-
125
- const storedDeadline = readDeadline();
126
- if (storedDeadline && Date.now() >= storedDeadline) {
127
- hardLogout('stored hard deadline reached');
128
- return;
129
- }
130
-
131
- try {
132
- const response = await fetch('./session?hard=1&ts=' + Date.now(), {
133
- credentials: 'include',
134
- cache: 'no-store',
135
- headers: { Accept: 'application/json' },
136
- });
137
- if (!response.ok) return;
138
- const session = await response.json();
139
- if (typeof session.expireInSec === 'number') {
140
- applyServerExpiration(session.expireInSec);
141
- }
142
- } catch (e) {
143
- // During update/restart the endpoint can be unavailable. Do not logout just because of a network error.
144
- }
145
- }
146
-
147
- function start() {
148
- checkSession();
149
- pollTimer = setInterval(checkSession, MIN_POLL_MS);
150
- window.addEventListener('focus', checkSession, { passive: true });
151
- document.addEventListener('visibilitychange', () => {
152
- if (!document.hidden) checkSession();
153
- });
154
- }
155
-
156
- window.NEXOWATT_EOS_HARD_LOGOUT = { version: VERSION, checkSession, hardLogout, clearStoredTokens, clearAuthCookies };
157
-
158
- if (document.readyState === 'loading') {
159
- document.addEventListener('DOMContentLoaded', start, { once: true });
160
- } else {
161
- start();
162
- }
3
+ // NexoWatt EOS v36: compatibility stub.
4
+ // The custom hard-logout timer was removed because it could expire sessions
5
+ // earlier than the configured admin TTL and broke native adapter dialogs.
6
+ // Session handling is now delegated to the same OAuth/session flow as the
7
+ // upstream ioBroker Admin.
8
+ const VERSION = '36';
9
+ function noop() {}
10
+ window.NEXOWATT_EOS_HARD_LOGOUT = {
11
+ version: VERSION,
12
+ checkSession: noop,
13
+ hardLogout: noop,
14
+ clearStoredTokens: noop,
15
+ clearAuthCookies: noop,
16
+ disabled: true,
17
+ };
163
18
  })();
@@ -220,6 +220,7 @@
220
220
  };
221
221
 
222
222
  const applyPolicyToDom = () => {
223
+ if (isAdapterConfigSurface()) return;
223
224
  const admin = isAdminUser();
224
225
  document.documentElement.classList.toggle('eos-security-admin-user', admin);
225
226
  document.documentElement.classList.toggle('eos-security-non-admin-user', !admin);
@@ -230,6 +231,8 @@
230
231
  hideEosSecuritySettingsForNonAdmins();
231
232
  };
232
233
 
234
+ const isAdapterConfigSurface = () => document.documentElement.classList.contains('eos-adapter-config-surface') || /Instanzeinstellungen:|Instance settings:|Geräteliste|Gerät hinzufügen|Gerät bearbeiten/i.test(document.body?.textContent || '');
235
+
233
236
  const scheduleApply = () => {
234
237
  if (state.scheduled) return;
235
238
  state.scheduled = true;
@@ -267,7 +270,7 @@
267
270
 
268
271
  document.addEventListener('click', event => {
269
272
  const target = event.target?.closest?.('button,[role="button"],a,[role="menuitem"],.MuiMenuItem-root');
270
- if (!target || isAdminUser()) return;
273
+ if (!target || isAdminUser() || isAdapterConfigSurface()) return;
271
274
  const label = normalizeFlat(`${target.textContent || ''} ${target.getAttribute?.('title') || ''} ${target.getAttribute?.('aria-label') || ''}`);
272
275
  if (/loschen|delete|remove|deinstall|uninstall/.test(label)) {
273
276
  target.classList.add('eos-security-hidden-delete');
package/build/lib/web.js CHANGED
@@ -506,6 +506,57 @@ class Web {
506
506
  });
507
507
  }
508
508
 
509
+
510
+ getSafeLoginOrigin(req) {
511
+ let origin = '';
512
+ try {
513
+ const url = new URL(req.url, 'http://127.0.0.1');
514
+ origin = url.searchParams.get('origin') || '';
515
+ }
516
+ catch {
517
+ const match = req.url.match(/[?&]origin=([^&]*)/);
518
+ origin = match?.[1] || '';
519
+ }
520
+ if (!origin) {
521
+ return null;
522
+ }
523
+ try {
524
+ origin = decodeURIComponent(origin);
525
+ }
526
+ catch {
527
+ // keep raw value and validate below
528
+ }
529
+ origin = String(origin || '').trim();
530
+ // Reject encoded hashes/login/logout/404 and hard-timeout parameters.
531
+ if (!origin || /(?:%2f|%23|#|login|logout|404|hard=|undefined|null)/i.test(origin)) {
532
+ return null;
533
+ }
534
+ origin = origin.split('?')[0];
535
+ const pos = origin.lastIndexOf('/');
536
+ if (pos > 0) {
537
+ origin = origin.substring(0, pos);
538
+ }
539
+ else if (pos === 0) {
540
+ origin = '';
541
+ }
542
+ if (!origin || origin === '.') {
543
+ return null;
544
+ }
545
+ if (/^https?:\/\//i.test(origin)) {
546
+ try {
547
+ const parsed = new URL(origin);
548
+ return parsed.pathname && parsed.pathname !== '/' ? parsed.pathname.replace(/\/+$/, '') : null;
549
+ }
550
+ catch {
551
+ return null;
552
+ }
553
+ }
554
+ if (!origin.startsWith('/')) {
555
+ return null;
556
+ }
557
+ return origin.replace(/\/+$/, '') || null;
558
+ }
559
+
509
560
  /**
510
561
  * Initialize the server
511
562
  */
@@ -532,6 +583,16 @@ class Web {
532
583
  this.server.app.get('/version', (_req, res) => {
533
584
  res.status(200).send(this.adapter.version);
534
585
  });
586
+ // v36: Repair stale/broken URLs generated by older EOS hard-logout builds.
587
+ this.server.app.use((req, res, next) => {
588
+ const requested = String(req.originalUrl || req.url || '');
589
+ if (/(?:%2f|%252f)(?:%23|%2523)|\/login\/|\/logout\/|hard=1/i.test(requested)
590
+ && /index\.html|login|hard=1|origin=|%23|%2523/i.test(requested)) {
591
+ res.redirect(this.LOGIN_PAGE);
592
+ return;
593
+ }
594
+ next();
595
+ });
535
596
  // replace socket.io
536
597
  this.server.app.use((req, res, next) => {
537
598
  const url = req.url.split('?')[0];
@@ -582,48 +643,16 @@ class Web {
582
643
  this.server.app.use(cookieParser());
583
644
  this.server.app.use(bodyParser.urlencoded({ extended: true }));
584
645
  this.server.app.use(bodyParser.json());
585
- // NexoWatt EOS: enforce the configured login timeout as a hard logout.
586
- // We remove refresh tokens from OAuth responses so the admin client cannot silently extend sessions.
587
- const eosHardLogout = this.adapter.config.nexowattHardLogout !== false;
588
- if (eosHardLogout) {
589
- this.server.app.use('/oauth/token', (req, res, next) => {
590
- const grantType = String(req.body?.grant_type || '');
591
- if (req.method === 'POST' && grantType === 'refresh_token') {
592
- res.status(401).json({
593
- error: 'invalid_grant',
594
- error_description: 'EOS session expired. Please log in again.',
595
- eosHardLogout: true,
596
- });
597
- return;
598
- }
599
- const originalJson = res.json.bind(res);
600
- res.json = body => {
601
- if (body && typeof body === 'object' && body.access_token && body.expires_in) {
602
- const expiresIn = Math.max(1, Math.round(Number(body.expires_in) || Number(this.settings.ttl) || 3600));
603
- body.refresh_token = '';
604
- body.refresh_token_expires_in = expiresIn;
605
- body.eosHardLogout = true;
606
- }
607
- return originalJson(body);
608
- };
609
- next();
610
- });
611
- }
646
+ // v36: OAuth/session handling intentionally follows upstream ioBroker Admin.
612
647
  this.oauth2Model = (0, webserver_1.createOAuth2Server)(this.adapter, {
613
648
  app: this.server.app,
614
649
  secure: this.settings.secure,
615
650
  accessLifetime: this.settings.ttl,
616
- refreshLifetime: this.settings.ttl,
651
+ refreshLifetime: 60 * 60 * 24 * 7, // 1 week, same as upstream admin
617
652
  noBasicAuth: this.settings.noBasicAuth,
618
653
  loginPage: (req) => {
619
654
  const isDev = req.url.includes('?dev');
620
- let origin = req.url.split('origin=')[1];
621
- if (origin) {
622
- const pos = origin.lastIndexOf('/');
623
- if (pos !== -1) {
624
- origin = origin.substring(0, pos);
625
- }
626
- }
655
+ const origin = this.getSafeLoginOrigin(req);
627
656
  if (isDev) {
628
657
  return 'http://127.0.0.1:3000/index.html?login';
629
658
  }
@@ -631,44 +660,44 @@ class Web {
631
660
  },
632
661
  });
633
662
  this.server.app.get('/session', (req, res) => {
634
- res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
635
- res.setHeader('Content-Type', 'application/json; charset=utf-8');
636
- if (!this.settings.auth) {
637
- res.json({ expireInSec: Math.max(120, this.settings.ttl || 3600), hardLogout: true, auth: false });
638
- return;
639
- }
640
- const tokenValue = this.readAccessTokenFromRequest(req);
641
- if (!tokenValue) {
642
- res.json({ expireInSec: 0, hardLogout: true, error: 'Cannot find session token' });
643
- return;
644
- }
645
- const candidates = new Set();
646
- candidates.add(tokenValue);
647
- candidates.add(tokenValue.startsWith('a:') ? tokenValue : `a:${tokenValue}`);
648
- if (tokenValue.length > 1) candidates.add(`a:${tokenValue[1]}`);
649
- const ids = Array.from(candidates);
650
- const readNext = (index) => {
651
- const id = ids[index];
652
- if (!id) {
653
- res.json({ expireInSec: 0, hardLogout: true, error: 'Cannot find session' });
663
+ // v36: Follow upstream admin semantics again. Do not run a second
664
+ // EOS hard-logout timer here; the official OAuth/session handling
665
+ // already uses the configured access lifetime.
666
+ if (req.headers.cookie) {
667
+ const cookies = req.headers.cookie.split(';').find(c => c.trim().startsWith('access_token='));
668
+ let tokenCookie = cookies?.split('=')[1];
669
+ if (!tokenCookie && req.headers.authorization?.startsWith('Bearer ')) {
670
+ tokenCookie = req.headers.authorization.split(' ')[1];
671
+ }
672
+ else if (!tokenCookie && req.query?.token) {
673
+ tokenCookie = req.query.token;
674
+ }
675
+ if (tokenCookie) {
676
+ const candidates = new Set();
677
+ candidates.add(tokenCookie.startsWith('a:') ? tokenCookie : `a:${tokenCookie}`);
678
+ if (tokenCookie.length > 1)
679
+ candidates.add(`a:${tokenCookie[1]}`);
680
+ const ids = Array.from(candidates);
681
+ const readNext = (index) => {
682
+ const id = ids[index];
683
+ if (!id) {
684
+ res.json({ expireInSec: 0 });
685
+ return;
686
+ }
687
+ void this.adapter.getSession(id, (token) => {
688
+ if (!token?.user) {
689
+ readNext(index + 1);
690
+ }
691
+ else {
692
+ res.json({ expireInSec: Math.round((token.aExp - Date.now()) / 1000) });
693
+ }
694
+ });
695
+ };
696
+ readNext(0);
654
697
  return;
655
698
  }
656
- void this.adapter.getSession(id, (token) => {
657
- if (!token?.user) {
658
- readNext(index + 1);
659
- return;
660
- }
661
- const now = Date.now();
662
- const expirations = [Number(token.aExp), Number(token.rExp), Number(token.expire), Number(token.expires), Number(token.expiresAt)].filter(value => Number.isFinite(value) && value > 0);
663
- const expiresAt = expirations.length ? Math.min(...expirations) : now + (this.settings.ttl || 3600) * 1000;
664
- res.json({
665
- expireInSec: Math.max(0, Math.floor((expiresAt - now) / 1000)),
666
- hardLogout: true,
667
- user: token.user,
668
- });
669
- });
670
- };
671
- readNext(0);
699
+ }
700
+ res.json({ error: 'Cannot find session' });
672
701
  });
673
702
  this.server.app.get(/.*\/nexowatt\/security\/(?:context|session)$/, (req, res) => {
674
703
  void this.sendEosSecuritySession(req, res).catch(e => {
@@ -690,13 +719,7 @@ class Web {
690
719
 
691
720
  this.server.app.get('/logout', (req, res) => {
692
721
  const isDev = req.url.includes('?dev');
693
- let origin = req.url.split('origin=')[1];
694
- if (origin) {
695
- const pos = origin.lastIndexOf('/');
696
- if (pos !== -1) {
697
- origin = origin.substring(0, pos);
698
- }
699
- }
722
+ const origin = this.getSafeLoginOrigin(req);
700
723
  for (const cookieName of ['access_token', 'refresh_token', 'connect.sid', 'io', 'ioBroker.sid', 'eos-admin.sid']) {
701
724
  res.clearCookie(cookieName, { path: '/' });
702
725
  }
@@ -1,8 +1,8 @@
1
- # NexoWatt EOS Admin v34
1
+ # NexoWatt EOS Admin v35
2
2
 
3
3
  ## Zweck
4
4
 
5
- Version 7.9.34 korrigiert zwei produktive Punkte:
5
+ Version 7.9.35 korrigiert zwei produktive Punkte:
6
6
 
7
7
  1. Repository-/Update-Metadaten zeigen vollständig auf die aktuelle npm-Version.
8
8
  2. Die konfigurierte Abmeldezeit wird als harte Sitzungslaufzeit erzwungen.
@@ -11,7 +11,7 @@ Version 7.9.34 korrigiert zwei produktive Punkte:
11
11
 
12
12
  In vorherigen Paketen konnten `common.meta`, `common.extIcon` und `common.readme` noch auf ältere unpkg-Versionen zeigen. Das konnte dazu führen, dass das Repository zwar eine neue Version anzeigt, der Admin beim Aktualisieren aber alte Metadaten nachlädt.
13
13
 
14
- v34 setzt diese Felder synchron auf `7.9.34`.
14
+ v35 setzt diese Felder synchron auf `7.9.35`.
15
15
 
16
16
  ## Harte Abmeldung
17
17
 
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "eos-admin",
4
- "version": "7.9.34",
4
+ "version": "7.9.36",
5
5
  "titleLang": {
6
6
  "en": "NexoWatt EOS Admin",
7
7
  "de": "NexoWatt EOS Admin",
@@ -18,9 +18,13 @@
18
18
  "connectionType": "local",
19
19
  "dataSource": "push",
20
20
  "news": {
21
- "7.9.34": {
22
- "en": "Fixed repository metadata for reliable EOS Admin updates and enforced hard logout after the configured login timeout.",
23
- "de": "Repository-Metadaten für zuverlässige EOS-Admin-Updates korrigiert und harte Abmeldung nach der eingestellten Abmeldezeit erzwungen."
21
+ "7.9.36": {
22
+ "en": "Restores official admin session handling, fixes bad login redirect paths, and enables full native adapter configuration compatibility without EOS overlays blocking adapter UI actions.",
23
+ "de": "Stellt die offizielle Admin-Sitzungslogik wieder her, korrigiert fehlerhafte Login-Redirect-Pfade und aktiviert volle native Adapter-Konfigurationskompatibilität ohne blockierende EOS-Overlays."
24
+ },
25
+ "7.9.35": {
26
+ "en": "Fixes EOS Admin login redirect/logout origin handling and restores reliable interaction with adapter instance configuration dialogs.",
27
+ "de": "Korrigiert den EOS-Admin Login-/Logout-Redirect und stellt die Bedienung von Adapter-Instanzkonfigurationen wieder zuverlässig her."
24
28
  },
25
29
  "7.9.31": {
26
30
  "en": "UI cleanup: fixes EOS Security German text encoding, removes the logout tile next to the compact navigation arrow, and expands EOS Assist with AI-ready multi-path setup guidance.",
@@ -202,7 +206,7 @@
202
206
  "icon": "admin.svg",
203
207
  "messagebox": true,
204
208
  "enabled": true,
205
- "extIcon": "https://unpkg.com/iobroker.eos-admin@7.9.34/admin/admin.svg",
209
+ "extIcon": "https://unpkg.com/iobroker.eos-admin@7.9.36/admin/admin.svg",
206
210
  "keywords": [
207
211
  "NexoWatt",
208
212
  "EOS",
@@ -213,7 +217,7 @@
213
217
  "licensed"
214
218
  ],
215
219
  "compact": true,
216
- "readme": "https://unpkg.com/iobroker.eos-admin@7.9.34/README.md",
220
+ "readme": "https://unpkg.com/iobroker.eos-admin@7.9.36/README.md",
217
221
  "authors": [
218
222
  "bluefox <bluefox@ccu.io>",
219
223
  "hobbyquaker <hq@ccu.io>"
@@ -282,7 +286,7 @@
282
286
  "nondeletable": false,
283
287
  "allowAdapterUpdate": true,
284
288
  "allowAdapterDelete": false,
285
- "meta": "https://unpkg.com/iobroker.eos-admin@7.9.34/io-package.json",
289
+ "meta": "https://unpkg.com/iobroker.eos-admin@7.9.36/io-package.json",
286
290
  "npmPackage": "iobroker.eos-admin"
287
291
  },
288
292
  "native": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "iobroker.eos-admin",
3
3
  "description": "NexoWatt EOS Admin standalone interface for Energy Operation System",
4
- "version": "7.9.34",
4
+ "version": "7.9.36",
5
5
  "contributors": [
6
6
  "bluefox <dogafox@gmail.com>",
7
7
  "apollon77",
package/public/404.html CHANGED
@@ -64,6 +64,18 @@
64
64
  color: #fff;
65
65
  }
66
66
  </style>
67
+
68
+ <script id="NEXOWATT_EOS_BAD_PATH_FIX">
69
+ (function () {
70
+ try {
71
+ var u = String(location.pathname + location.search + location.hash);
72
+ if (/(%2F%23|%252F%2523|hard=1|\/login\/|\/logout\/)/i.test(u)) {
73
+ location.replace('/index.html?login');
74
+ }
75
+ } catch (e) {}
76
+ })();
77
+ </script>
78
+
67
79
  </head>
68
80
 
69
81
  <body>
@@ -56,8 +56,11 @@ if (!bootstrap.includes('window.adapterName="eos-admin"')) fail('frontend bootst
56
56
  if (bootstrap.includes('window.adapterName="admin"')) fail('frontend bootstrap still contains window.adapterName="admin"');
57
57
 
58
58
  const webBuild = fs.readFileSync(path.join(root, 'build/lib/web.js'), 'utf8');
59
- if (!webBuild.includes("body.refresh_token = '';")) fail('build/lib/web.js does not remove OAuth refresh tokens for hard logout');
60
- if (!webBuild.includes("grantType === 'refresh_token'")) fail('build/lib/web.js does not reject refresh_token grants');
61
- if (!webBuild.includes('refreshLifetime: this.settings.ttl')) fail('build/lib/web.js does not bind refresh lifetime to ttl');
59
+ const branding = fs.readFileSync(path.join(root, 'adminWww/js/eos-branding.js'), 'utf8');
60
+ if (!webBuild.includes('refreshLifetime: 60 * 60 * 24 * 7')) fail('build/lib/web.js must keep upstream-compatible refresh lifetime');
61
+ if (!webBuild.includes('Follow upstream admin semantics again')) fail('build/lib/web.js does not contain the v36 session compatibility fix');
62
+ if (index.includes('eos-hard-logout.js')) fail('adminWww/index.html must not load the removed custom hard-logout timer');
63
+ if (!branding.includes('isAdapterConfigSurface')) fail('eos-branding.js lacks native adapter config safe-mode detection');
64
+ if (!branding.includes('Adapter UIs must remain 100% functional')) fail('eos-branding.js lacks native adapter config interaction guard');
62
65
 
63
66
  console.log('[NexoWatt EOS package validation] OK');