iobroker.eos-admin 7.9.93 → 7.9.95

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.
Files changed (45) hide show
  1. package/INSTALL_TEST_V7.9.95.md +15 -0
  2. package/NEXOWATT_EOS_BUILD_INFO.json +23 -18
  3. package/NEXOWATT_EOS_STABLE_7.9.94.md +16 -0
  4. package/{PUBLISH_STABLE_V7.9.93.md → PUBLISH_STABLE_V7.9.95.md} +2 -5
  5. package/README_STABILITY_V7.9.95.md +12 -0
  6. package/RELEASE_ACCEPTANCE_V7.9.95.md +11 -0
  7. package/RELEASE_NOTES_V7.9.95.md +12 -0
  8. package/adminWww/assets/Adapters-B5_jQ7DE-v84.js +1 -1
  9. package/adminWww/css/nexowatt-native-shell.css +4 -156
  10. package/adminWww/index.html +13 -11
  11. package/adminWww/js/eos-account-management.js +1 -1
  12. package/adminWww/js/eos-assistant.js +5 -556
  13. package/adminWww/js/eos-basic-settings.js +1 -1
  14. package/adminWww/js/eos-branding-sanitizer.js +1 -3
  15. package/adminWww/js/eos-native-security.js +1 -1
  16. package/adminWww/js/eos-policy-client.js +1 -1
  17. package/adminWww/js/eos-role-bootstrap.js +2 -2
  18. package/adminWww/js/eos-role-ui.js +1 -1
  19. package/adminWww/js/nexowatt-native-shell.js +1 -1
  20. package/adminWww/static/js/nexowatt-stable-login.js +79 -0
  21. package/build/lib/chat/assistantKnowledge.js +6 -21
  22. package/build/lib/chat/chatOrchestrator.js +38 -33
  23. package/build/lib/chat/mcpClientManager.js +1 -1
  24. package/build/lib/nexowattStableAuth.js +74 -0
  25. package/build/lib/web.js +24 -7
  26. package/build/main.js +123 -308
  27. package/io-package.json +20 -16
  28. package/package.json +23 -32
  29. package/INSTALL_TEST_V7.9.93.md +0 -12
  30. package/README_STABILITY_V7.9.93.md +0 -15
  31. package/RELEASE_ACCEPTANCE_V7.9.93.md +0 -15
  32. package/RELEASE_NOTES_V7.9.93.md +0 -10
  33. package/tools/nexowatt-account-management-selftest.cjs +0 -61
  34. package/tools/nexowatt-clean-legacy-runtime.cjs +0 -147
  35. package/tools/nexowatt-ensure-release-defaults.cjs +0 -72
  36. package/tools/nexowatt-generate-eos-admin-repo-entry.cjs +0 -37
  37. package/tools/nexowatt-generate-repo-entry.cjs +0 -3
  38. package/tools/nexowatt-internal-reserve-selftest.cjs +0 -57
  39. package/tools/nexowatt-login-layout-selftest.cjs +0 -62
  40. package/tools/nexowatt-modern-ui-selftest.cjs +0 -50
  41. package/tools/nexowatt-patch-repo.cjs +0 -54
  42. package/tools/nexowatt-publish-channel-guard.cjs +0 -58
  43. package/tools/nexowatt-release-defaults-selftest.cjs +0 -29
  44. package/tools/nexowatt-runtime-cleanup-selftest.cjs +0 -47
  45. package/tools/nexowatt-validate-package.cjs +0 -246
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "iobroker.eos-admin",
3
- "description": "NexoWatt EOS Admin test candidate with compact login, visible NexoWatt publisher and live role-aware EOS Assist",
4
- "version": "7.9.93",
3
+ "description": "NexoWatt EOS Admin stable product release with compact login, role-safe services and self-healing sales defaults",
4
+ "version": "7.9.95",
5
5
  "contributors": [
6
6
  "bluefox <dogafox@gmail.com>",
7
7
  "apollon77",
@@ -86,7 +86,7 @@
86
86
  "main": "build/main.js",
87
87
  "files": [
88
88
  "admin/",
89
- "build",
89
+ "build/",
90
90
  "docs/",
91
91
  "adminWww/",
92
92
  "public/",
@@ -94,31 +94,17 @@
94
94
  "LICENSE",
95
95
  "THIRD_PARTY_NOTICES.md",
96
96
  "NEXOWATT_PROPRIETARY_LICENSE.md",
97
- "admin/LICENSE-NEXOWATT.md",
98
- "adminWww/LICENSE-NEXOWATT.md",
99
97
  "NEXOWATT_PUBLIC_NPM_DISTRIBUTION.md",
100
- "tools/nexowatt-publish-channel-guard.cjs",
101
- "tools/nexowatt-validate-package.cjs",
102
98
  "README.md",
103
- "tools/nexowatt-generate-repo-entry.cjs",
104
- "tools/nexowatt-patch-repo.cjs",
105
99
  "NEXOWATT_EOS_BUILD_INFO.json",
106
100
  "NEXOWATT_EOS_STANDALONE.md",
107
- "tools/nexowatt-generate-eos-admin-repo-entry.cjs",
108
- "tools/nexowatt-repair-eos-admin-update.cjs",
109
- "tools/nexowatt-clean-legacy-runtime.cjs",
110
- "tools/nexowatt-runtime-cleanup-selftest.cjs",
111
- "tools/nexowatt-account-management-selftest.cjs",
112
- "tools/nexowatt-modern-ui-selftest.cjs",
113
- "tools/nexowatt-login-layout-selftest.cjs",
114
- "tools/nexowatt-internal-reserve-selftest.cjs",
115
- "tools/nexowatt-ensure-release-defaults.cjs",
116
- "tools/nexowatt-release-defaults-selftest.cjs",
117
- "README_STABILITY_V7.9.93.md",
118
- "RELEASE_NOTES_V7.9.93.md",
119
- "PUBLISH_STABLE_V7.9.93.md",
120
- "INSTALL_TEST_V7.9.93.md",
121
- "RELEASE_ACCEPTANCE_V7.9.93.md"
101
+ "NEXOWATT_EOS_STABLE_7.9.94.md",
102
+ "README_STABILITY_V7.9.95.md",
103
+ "RELEASE_NOTES_V7.9.95.md",
104
+ "PUBLISH_STABLE_V7.9.95.md",
105
+ "INSTALL_TEST_V7.9.95.md",
106
+ "RELEASE_ACCEPTANCE_V7.9.95.md",
107
+ "tools/nexowatt-repair-eos-admin-update.cjs"
122
108
  ],
123
109
  "scripts": {
124
110
  "npm": "npm i -f && cd src-admin && npm i -f",
@@ -129,7 +115,7 @@
129
115
  "test:integration": "mocha test/integration --exit && npm run test:gui && npm run test:rule && npm run test:unit",
130
116
  "test:rule": "mocha test/rule --exit",
131
117
  "test:gui": "mocha test/*.gui.js --exit",
132
- "prepublishOnly": "npm run prepare:eos-release-defaults && npm run check:eos-publish-channel && npm run check:eos-package && npm run check:eos-stability",
118
+ "prepublishOnly": "npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run check:eos-publish-channel && npm run check:eos-package && npm run check:eos-stability",
133
119
  "build": "npm run build:frontend && npm run build:backend && npm run clean:eos-runtime",
134
120
  "build:backend": "tsc -p tsconfig.build.json && tsx tasks.mts --backend-i18n",
135
121
  "build:frontend": "tsx tasks.mts",
@@ -153,12 +139,12 @@
153
139
  "nexowatt:repo-entry": "node tools/nexowatt-generate-repo-entry.cjs",
154
140
  "nexowatt:patch-repo": "node tools/nexowatt-patch-repo.cjs",
155
141
  "nexowatt:repair-update": "node tools/nexowatt-repair-eos-admin-update.cjs",
156
- "check:eos-stability": "node tools/nexowatt-stability-check.cjs && node tools/nexowatt-esm-syntax-selftest.cjs && node tools/nexowatt-import-integrity-selftest.cjs && node tools/nexowatt-entrypoint-smoke-selftest.cjs && node tools/nexowatt-frontend-graph-check.cjs && node tools/nexowatt-policy-selftest.cjs && node tools/nexowatt-publish-channel-selftest.cjs && node tools/nexowatt-release-defaults-selftest.cjs && node tools/nexowatt-role-access-selftest.cjs && node tools/nexowatt-internal-reserve-selftest.cjs && node tools/nexowatt-first-login-selftest.cjs && node tools/nexowatt-account-management-selftest.cjs && node tools/nexowatt-modern-ui-selftest.cjs && node tools/nexowatt-login-layout-selftest.cjs && node tools/nexowatt-branding-selftest.cjs && node tools/nexowatt-default-port-selftest.cjs && node tools/nexowatt-module-popup-selftest.cjs && node tools/nexowatt-datapoint-selftest.cjs && node tools/nexowatt-update-selftest.cjs && node tools/nexowatt-datapoint-interaction-selftest.cjs && node tools/nexowatt-manual-write-policy-selftest.cjs && node tools/nexowatt-value-column-selftest.cjs && node tools/nexowatt-native-shell-selftest.cjs && node tools/nexowatt-assistant-separation-selftest.cjs && node tools/nexowatt-runtime-cleanup-selftest.cjs",
142
+ "check:eos-stability": "node tools/nexowatt-stability-check.cjs && node tools/nexowatt-esm-syntax-selftest.cjs && node tools/nexowatt-import-integrity-selftest.cjs && node tools/nexowatt-entrypoint-smoke-selftest.cjs && node tools/nexowatt-frontend-graph-check.cjs && node tools/nexowatt-policy-selftest.cjs && node tools/nexowatt-publish-channel-selftest.cjs && node tools/nexowatt-release-defaults-selftest.cjs && node tools/nexowatt-role-access-selftest.cjs && node tools/nexowatt-internal-reserve-selftest.cjs && node tools/nexowatt-first-login-selftest.cjs && node tools/nexowatt-account-management-selftest.cjs && node tools/nexowatt-modern-ui-selftest.cjs && node tools/nexowatt-login-layout-selftest.cjs && node tools/nexowatt-branding-selftest.cjs && node tools/nexowatt-default-port-selftest.cjs && node tools/nexowatt-module-popup-selftest.cjs && node tools/nexowatt-datapoint-selftest.cjs && node tools/nexowatt-update-selftest.cjs && node tools/nexowatt-datapoint-interaction-selftest.cjs && node tools/nexowatt-manual-write-policy-selftest.cjs && node tools/nexowatt-value-column-selftest.cjs && node tools/nexowatt-native-shell-selftest.cjs && node tools/nexowatt-assistant-separation-selftest.cjs && node tools/nexowatt-runtime-cleanup-selftest.cjs && node tools/nexowatt-version-sync-selftest.cjs && node tools/nexowatt-merge-update-selftest.cjs && npm run check:eos-stable-v95",
157
143
  "nexowatt:patch-built-frontend": "node tools/nexowatt-patch-built-frontend.cjs",
158
144
  "clean:eos-runtime": "node tools/nexowatt-clean-legacy-runtime.cjs",
159
- "precheck:eos-package": "npm run prepare:eos-release-defaults && npm run clean:eos-runtime",
160
- "precheck:eos-stability": "npm run prepare:eos-release-defaults && npm run clean:eos-runtime",
161
- "prepack": "node tools/nexowatt-clean-legacy-runtime.cjs --quiet",
145
+ "precheck:eos-package": "npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run clean:eos-runtime",
146
+ "precheck:eos-stability": "npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run clean:eos-runtime",
147
+ "prepack": "node tools/nexowatt-sync-release-version.cjs --quiet && node tools/nexowatt-clean-legacy-runtime.cjs --quiet",
162
148
  "check:eos-esm": "node tools/nexowatt-esm-syntax-selftest.cjs",
163
149
  "check:eos-imports": "node tools/nexowatt-import-integrity-selftest.cjs",
164
150
  "check:eos-release": "npm run check:eos-package && npm run check:eos-stability && npm pack --dry-run",
@@ -173,7 +159,11 @@
173
159
  "test:eos-login-layout": "node tools/nexowatt-login-layout-selftest.cjs",
174
160
  "test:eos-release-defaults": "node tools/nexowatt-release-defaults-selftest.cjs",
175
161
  "prepare:eos-release-defaults": "node tools/nexowatt-ensure-release-defaults.cjs",
176
- "normalize:eos-release": "npm run prepare:eos-release-defaults"
162
+ "normalize:eos-release": "npm run prepare:eos-release-defaults",
163
+ "sync:eos-version": "node tools/nexowatt-sync-release-version.cjs",
164
+ "test:eos-version-sync": "node tools/nexowatt-version-sync-selftest.cjs",
165
+ "verify:eos-merge": "node tools/nexowatt-merge-update-selftest.cjs",
166
+ "check:eos-stable-v95": "node tools/nexowatt-stable-v95-selftest.cjs"
177
167
  },
178
168
  "author": "NexoWatt",
179
169
  "private": false,
@@ -184,6 +174,7 @@
184
174
  },
185
175
  "nexowattReleasePolicy": {
186
176
  "distTag": "latest",
187
- "purpose": "test candidate for accepted stable NexoWatt EOS sales-product release 7.9.93"
188
- }
177
+ "purpose": "accepted stable NexoWatt EOS sales-product release 7.9.95"
178
+ },
179
+ "publisher": "NexoWatt"
189
180
  }
@@ -1,12 +0,0 @@
1
- # Installationstest 7.9.93
2
-
3
- ```bash
4
- cd /opt/iobroker
5
- iobroker backup
6
- iobroker stop eos-admin.0
7
- npm install --no-save --omit=dev /PFAD/iobroker.eos-admin-7.9.93.tgz
8
- iobroker upload eos-admin
9
- iobroker restart eos-admin.0
10
- ```
11
-
12
- Prüfen: Login ohne Scrollbalken, Modul-Suche `[NexoWatt]`, EOS-Assist-Konfiguration als Admin, Live-Fragen mit allen drei Rollen, Dienste-/Reservefilter, Neustart und Backup-Rücklesetest.
@@ -1,15 +0,0 @@
1
- # NexoWatt EOS Admin 7.9.93 – Testkandidat
2
-
3
- Dieser Stand basiert auf der freigegebenen Admin-7-Linie und ist für den abschließenden Realtest vorgesehen.
4
-
5
- ## Änderungen
6
-
7
- - kompakte Anmeldung ohne internen Scrollbalken
8
- - sichtbarer Herausgeber „NexoWatt“ in der Modulinstallation
9
- - EOS Assist mit authentifizierter, rollenabhängiger Live-Systemabfrage
10
- - EOS Assist bleibt schreibgeschützt und respektiert die Rechte von Admin, Installateur und Endkunde
11
- - technischer Paketname `iobroker.eos-admin` bleibt für Installation und Kompatibilität unverändert
12
-
13
- ## Freigabe
14
-
15
- Erst nach bestandenem Anlagen-, Rollen-, Reboot- und Backup-Test darf 7.9.93 auf npm `latest` gesetzt werden.
@@ -1,15 +0,0 @@
1
- # Release-Abnahme 7.9.93
2
-
3
- - [ ] Login-Karte ohne inneren Scrollbalken
4
- - [ ] sichtbare Modulbezeichnung `eos-admin [NexoWatt]`
5
- - [ ] technischer Paketname bleibt installierbar
6
- - [ ] EOS Assist durch Admin/Service konfigurierbar
7
- - [ ] EOS Assist liest reale Systemdaten statt statischer Texte
8
- - [ ] Admin erhält vollständige lesende Systemauskunft
9
- - [ ] Installateur erhält nur freigegebene Inbetriebnahme-/Diagnosedaten
10
- - [ ] Endkunde erhält nur freigegebene Smart-Home-/Betriebsdaten
11
- - [ ] EOS Assist kann keine Zustände oder Einstellungen schreiben
12
- - [ ] `admin.0` und `backitup.0` bleiben für Nicht-Admins verborgen
13
- - [ ] NexoWatt Backup funktioniert
14
- - [ ] Controller-Neustart bestanden
15
- - [ ] Rollback auf 7.9.86 bestanden
@@ -1,10 +0,0 @@
1
- # Release Notes – NexoWatt EOS Admin 7.9.93
2
-
3
- ## Anmeldung
4
- Der unnötige vertikale Scrollbalken in der kompakten Login-Karte wurde entfernt.
5
-
6
- ## Sichtbarer Herausgeber
7
- In der Modulinstallation erscheint bei `eos-admin` sichtbar nur noch `[NexoWatt]`. Die technische npm-Kennung bleibt intern unverändert.
8
-
9
- ## EOS Assist
10
- EOS Assist verwendet jetzt den angemeldeten Benutzer, dessen EOS-Rolle und die freigegebenen Lesewerkzeuge. Nach Konfiguration von Anbieter, Zugang und Modell durch Admin/Service kann der Assistent Fragen zu realen Modulen, Diensten, Einstellungen, Geräten, Datenpunkten, Räumen/Funktionen, Logs, Historie und Sicherungen beantworten. Schreibzugriffe sind in diesem Stand nicht zulässig.
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- const fs = require('fs');
4
- const path = require('path');
5
- const root = path.resolve(__dirname, '..');
6
- const read = rel => fs.readFileSync(path.join(root, rel), 'utf8');
7
- const json = rel => JSON.parse(read(rel));
8
- let bad = false;
9
- const fail = msg => { console.error(`[NexoWatt EOS account management] ${msg}`); bad = true; };
10
-
11
- const mainSource = read('src/main.ts');
12
- const mainBuilt = read('build/main.js');
13
- const webSource = read('src/lib/web.ts');
14
- const webBuilt = read('build/lib/web.js');
15
- const sourceUi = read('src-admin/public/js/eos-account-management.js');
16
- const builtUi = read('adminWww/js/eos-account-management.js');
17
- const roleUi = read('adminWww/js/eos-role-ui.js');
18
- const css = read('adminWww/css/nexowatt-native-shell.css');
19
- const index = read('adminWww/index.html');
20
- const info = json('NEXOWATT_EOS_BUILD_INFO.json');
21
- const shellTag = String(info.shellCacheTag || info.shellCacheVersion);
22
-
23
- for (const code of [mainSource, mainBuilt]) {
24
- for (const marker of [
25
- 'system.user.installer', 'system.user.guest', 'ensureEosDefaultRoleUsers', 'unknown random bootstrap secret',
26
- 'eosPasswordSetupRequired', 'personal password setup is required',
27
- ]) if (!code.includes(marker)) fail(`main account marker missing: ${marker}`);
28
- }
29
- for (const code of [webSource, webBuilt]) {
30
- for (const marker of [
31
- 'getEosManagedAccounts', 'sendEosAccountManagement', 'resetEosAccountPassword',
32
- '/nexowatt/account/manage', '/nexowatt/account/reset', 'x-nexowatt-eos-account-reset',
33
- 'canResetInstaller', 'canResetEndUser', "targetUserId === 'system.user.admin'", 'targetUserId === access.userId',
34
- "access.role === 'installer' && explicitlyManagedRole !== 'enduser'",
35
- 'explicit member of a managed EOS installer/end-user group', 'passwordResetAt', 'passwordResetBy',
36
- "passwordResetMode = 'passwordless-first-activation'", 'accountDisabled',
37
- ]) if (!code.includes(marker)) fail(`web account marker missing: ${marker}`);
38
- if (!/randomBytes[^\n]{0,40}48/.test(code)) fail('reset does not generate an unknown random bootstrap secret');
39
- if (!code.includes('const explicitInstaller = targetAccess.groups.some')) fail('reset target is not restricted to explicit installer membership');
40
- if (!code.includes('const explicitEndUser = targetAccess.groups.some')) fail('reset target is not restricted to explicit end-user membership');
41
- }
42
-
43
- for (const marker of [
44
- 'v93-account-management-under-access-rights', "['admin', 'installer']", 'nexowatt/account/manage',
45
- 'nexowatt/account/reset', 'X-NexoWatt-EOS-Account-Reset', 'data.canResetInstaller === true',
46
- "account.role === 'enduser'", 'Admin/Service', 'Installateure', 'NEXOWATT_EOS_ACCOUNT_MANAGEMENT',
47
- 'ensureEntrySurface', "currentRoute() !== 'tab-users'", 'eos-account-management-entry',
48
- ]) if (!sourceUi.includes(marker)) fail(`account UI marker missing: ${marker}`);
49
- if (sourceUi.includes("launcher.className = 'eos-account-management-launcher'")) fail('standalone account launcher is still created');
50
- if (sourceUi.includes('new MutationObserver')) fail('account management adds a second broad MutationObserver');
51
- if (sourceUi !== builtUi) fail('account management source/build drift');
52
- if (!roleUi.includes("route === 'tab-users'")) fail('installer cannot reach Zugänge & Rechte');
53
- if (roleUi.includes('NEXOWATT_EOS_ACCOUNT_MANAGEMENT.open')) fail('role overview opens account management outside Zugänge & Rechte');
54
- if (!index.includes(`eos-account-management.js?v=${shellTag}`)) fail('account management asset is not active with the current cache tag');
55
- for (const marker of [
56
- '.eos-account-management-entry', '.eos-account-management-overlay', '.eos-account-management-dialog',
57
- '.eos-account-row', '.eos-account-reset', 'html.eos-account-page-installer',
58
- ]) if (!css.includes(marker)) fail(`account management CSS marker missing: ${marker}`);
59
-
60
- if (bad) process.exit(1);
61
- console.log('[NexoWatt EOS account management] OK');
@@ -1,147 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const fs = require('fs');
5
- const os = require('os');
6
- const path = require('path');
7
-
8
- const DEFAULT_ROOT = path.resolve(__dirname, '..');
9
- const LEGACY_OVERLAYS = [
10
- 'adminWww/js/eos-branding.js',
11
- 'adminWww/js/eos-security-ui.js',
12
- 'adminWww/js/eos-console-quiet.js',
13
- 'adminWww/js/eos-objects-state-tools.js',
14
- 'adminWww/js/eos-performance-guard.js',
15
- 'adminWww/js/eos-runtime-fixes.js',
16
- 'adminWww/js/eos-hard-logout.js',
17
- 'adminWww/css/eos-branding.css',
18
- 'src-admin/public/js/eos-branding.js',
19
- 'src-admin/public/js/eos-security-ui.js',
20
- 'src-admin/public/js/eos-console-quiet.js',
21
- 'src-admin/public/js/eos-objects-state-tools.js',
22
- 'src-admin/public/js/eos-performance-guard.js',
23
- 'src-admin/public/js/eos-runtime-fixes.js',
24
- 'src-admin/public/js/eos-hard-logout.js',
25
- 'src-admin/public/css/eos-branding.css',
26
- ];
27
-
28
- const readJson = file => JSON.parse(fs.readFileSync(file, 'utf8'));
29
-
30
- function runtimeNumber(root) {
31
- const info = readJson(path.join(root, 'NEXOWATT_EOS_BUILD_INFO.json'));
32
- const value = Number(String(info.runtimeEntry || '').replace(/^v/, ''));
33
- if (!Number.isFinite(value)) {
34
- throw new Error(`Invalid runtimeEntry in NEXOWATT_EOS_BUILD_INFO.json: ${info.runtimeEntry}`);
35
- }
36
- return value;
37
- }
38
-
39
- function walkFiles(dir) {
40
- if (!fs.existsSync(dir)) return [];
41
- const result = [];
42
- const stack = [dir];
43
- while (stack.length) {
44
- const current = stack.pop();
45
- for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
46
- const absolute = path.join(current, entry.name);
47
- if (entry.isDirectory()) stack.push(absolute);
48
- else if (entry.isFile()) result.push(absolute);
49
- }
50
- }
51
- return result;
52
- }
53
-
54
- function isLegacyVersionedRuntime(file, activeRuntime) {
55
- const name = path.basename(file);
56
- const versionMatch = name.match(/-v(\d+)\.(?:js|js\.map|css|css\.map)$/i);
57
- if (versionMatch) return Number(versionMatch[1]) !== activeRuntime;
58
- const remoteMatch = name.match(/^remoteEntry-v(\d+)\.(?:js|js\.map)$/i);
59
- if (remoteMatch) return Number(remoteMatch[1]) !== activeRuntime;
60
-
61
- // Remove historical emergency bundles which predate the consolidated runtime
62
- // naming and must never survive in a current EOS Admin source tree.
63
- return /(?:DPWrite|DPAdapter|DPw\d+|NoLock|Unrestricted|force-version|delete-services-hardfix)/i.test(name) && /\.(?:js|js\.map)$/i.test(name);
64
- }
65
-
66
- function collectLegacyRuntimeFiles(root = DEFAULT_ROOT) {
67
- const activeRuntime = runtimeNumber(root);
68
- const scanRoots = [
69
- path.join(root, 'adminWww', 'assets'),
70
- path.join(root, 'adminWww'),
71
- path.join(root, 'src-admin', 'build', 'assets'),
72
- path.join(root, 'src-admin', 'build'),
73
- ];
74
- const files = new Set();
75
- for (const scanRoot of scanRoots) {
76
- for (const file of walkFiles(scanRoot)) {
77
- if (isLegacyVersionedRuntime(file, activeRuntime)) files.add(file);
78
- }
79
- }
80
- for (const rel of LEGACY_OVERLAYS) {
81
- const file = path.join(root, rel);
82
- if (fs.existsSync(file)) files.add(file);
83
- }
84
- return { activeRuntime, files: [...files].sort() };
85
- }
86
-
87
- function cleanLegacyRuntime(options = {}) {
88
- const root = path.resolve(options.root || DEFAULT_ROOT);
89
- const dryRun = options.dryRun === true;
90
- const quiet = options.quiet === true;
91
- const silent = options.silent === true;
92
- const { activeRuntime, files } = collectLegacyRuntimeFiles(root);
93
- const removed = [];
94
- const failed = [];
95
-
96
- for (const file of files) {
97
- if (dryRun) {
98
- removed.push(file);
99
- continue;
100
- }
101
- try {
102
- try {
103
- fs.rmSync(file, { force: true });
104
- } catch (firstError) {
105
- // ZIP extraction tools on Windows may preserve a read-only bit. Make a
106
- // single controlled retry before reporting a real cleanup failure.
107
- try { fs.chmodSync(file, 0o666); } catch (_) { /* best effort */ }
108
- fs.rmSync(file, { force: true });
109
- }
110
- if (!fs.existsSync(file)) removed.push(file);
111
- else failed.push({ file, error: 'file still exists after removal' });
112
- } catch (error) {
113
- failed.push({ file, error: error?.message || String(error) });
114
- }
115
- }
116
-
117
- if (failed.length) {
118
- const details = failed.map(item => `${path.relative(root, item.file)}: ${item.error}`).join(os.EOL);
119
- throw new Error(`Could not remove ${failed.length} legacy runtime file(s):${os.EOL}${details}`);
120
- }
121
-
122
- if (!silent) {
123
- if (!quiet) {
124
- console.log(`[NexoWatt EOS runtime cleanup] OK (runtime v${activeRuntime}, removed ${removed.length} legacy file${removed.length === 1 ? '' : 's'})`);
125
- } else if (removed.length) {
126
- console.log(`[NexoWatt EOS runtime cleanup] removed ${removed.length} legacy runtime files before validation`);
127
- }
128
- }
129
-
130
- return { activeRuntime, removed };
131
- }
132
-
133
- if (require.main === module) {
134
- try {
135
- cleanLegacyRuntime({ dryRun: process.argv.includes('--dry-run'), quiet: process.argv.includes('--quiet') });
136
- } catch (error) {
137
- console.error(`[NexoWatt EOS runtime cleanup] ERROR: ${error?.stack || error}`);
138
- process.exit(1);
139
- }
140
- }
141
-
142
- module.exports = {
143
- LEGACY_OVERLAYS,
144
- collectLegacyRuntimeFiles,
145
- cleanLegacyRuntime,
146
- isLegacyVersionedRuntime,
147
- };
@@ -1,72 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const fs = require('node:fs');
5
- const path = require('node:path');
6
-
7
- const CANONICAL_NATIVE_DEFAULTS = Object.freeze({
8
- auth: true,
9
- port: 8081,
10
- eosLockLegacyAdmin: true,
11
- eosHideLegacyAdminFromNonAdmins: true,
12
- eosHideLegacyBackupFromNonAdmins: true,
13
- nexowattHideLegacyBackupFromNonAdmins: true,
14
- eosRequireFirstLoginPassword: true,
15
- });
16
-
17
- /**
18
- * Enforce mandatory source defaults for every NexoWatt EOS sales release.
19
- * This normalizes the repository io-package.json only. Existing installed
20
- * instance configuration is not overwritten during adapter startup.
21
- */
22
- function ensureReleaseDefaults(ioPackage) {
23
- if (!ioPackage || typeof ioPackage !== 'object' || Array.isArray(ioPackage)) {
24
- throw new TypeError('io-package.json must contain a JSON object');
25
- }
26
- const native = ioPackage.native && typeof ioPackage.native === 'object' && !Array.isArray(ioPackage.native)
27
- ? ioPackage.native
28
- : (ioPackage.native = {});
29
- const changes = [];
30
- for (const [key, value] of Object.entries(CANONICAL_NATIVE_DEFAULTS)) {
31
- if (native[key] !== value) {
32
- changes.push({ key, previous: native[key], value });
33
- native[key] = value;
34
- }
35
- }
36
- return {
37
- ioPackage,
38
- changed: changes.length > 0,
39
- fields: changes.map(change => `native.${change.key}`),
40
- changes,
41
- };
42
- }
43
-
44
- function ensureFile(filePath) {
45
- const absolute = path.resolve(filePath);
46
- const parsed = JSON.parse(fs.readFileSync(absolute, 'utf8'));
47
- const result = ensureReleaseDefaults(parsed);
48
- if (result.changed) {
49
- fs.writeFileSync(absolute, `${JSON.stringify(result.ioPackage, null, 2)}\n`, 'utf8');
50
- }
51
- return { file: absolute, ...result };
52
- }
53
-
54
- if (require.main === module) {
55
- const root = path.resolve(__dirname, '..');
56
- const target = process.argv[2] || path.join(root, 'io-package.json');
57
- try {
58
- const result = ensureFile(target);
59
- if (result.changed) {
60
- console.log(
61
- `[NexoWatt EOS release defaults] repaired ${result.changes.length} canonical value(s): ${result.changes.map(change => change.key).join(', ')}`,
62
- );
63
- } else {
64
- console.log('[NexoWatt EOS release defaults] OK (canonical sales defaults already present)');
65
- }
66
- } catch (error) {
67
- console.error(`[NexoWatt EOS release defaults] ${error instanceof Error ? error.message : String(error)}`);
68
- process.exit(1);
69
- }
70
- }
71
-
72
- module.exports = { CANONICAL_NATIVE_DEFAULTS, ensureReleaseDefaults, ensureFile };
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- const pkg = require('../package.json');
4
- const io = require('../io-package.json');
5
- const version = io.common.version || pkg.version;
6
- const base = (process.argv[2] || `https://unpkg.com/iobroker.eos-admin@${version}`).replace(/\/$/, '');
7
- const entry = {
8
- 'eos-admin': {
9
- name: 'eos-admin',
10
- version,
11
- title: 'NexoWatt EOS Admin',
12
- titleLang: io.common.titleLang,
13
- desc: io.common.desc,
14
- news: io.common.news,
15
- meta: `${base}/io-package.json`,
16
- icon: `${base}/admin/admin.png`,
17
- extIcon: `${base}/admin/admin.svg`,
18
- type: io.common.type || 'general',
19
- mode: io.common.mode || 'daemon',
20
- platform: io.common.platform || 'Javascript/Node.js',
21
- connectionType: io.common.connectionType || 'local',
22
- dataSource: io.common.dataSource || 'push',
23
- adminUI: io.common.adminUI || { config: 'json' },
24
- license: io.common.license || 'NexoWatt Proprietary',
25
- licenseInformation: io.common.licenseInformation,
26
- dependencies: io.common.dependencies || [{ 'js-controller': '>=6.0.11' }],
27
- stopBeforeUpdate: false,
28
- dontDelete: false,
29
- nondeletable: false,
30
- readme: `${base}/README.md`,
31
- packetName: 'iobroker.eos-admin',
32
- npmPackage: 'iobroker.eos-admin',
33
- allowAdapterUpdate: true,
34
- allowAdapterDelete: false,
35
- }
36
- };
37
- console.log(JSON.stringify(entry, null, 2));
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- require('./nexowatt-generate-eos-admin-repo-entry.cjs');
@@ -1,57 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- const fs = require('fs');
4
- const path = require('path');
5
- const root = path.resolve(__dirname, '..');
6
- const read = rel => fs.readFileSync(path.join(root, rel), 'utf8');
7
- const json = rel => JSON.parse(read(rel));
8
- let bad = false;
9
- const fail = msg => { console.error(`[NexoWatt EOS internal reserve] ${msg}`); bad = true; };
10
-
11
- const mainSource = read('src/main.ts');
12
- const mainBuilt = read('build/main.js');
13
- const webSource = read('src/lib/web.ts');
14
- const webBuilt = read('build/lib/web.js');
15
- const role = read('adminWww/js/eos-role-ui.js');
16
- const boot = read('adminWww/js/eos-role-bootstrap.js');
17
- const drawer = read('src-admin/src/components/Drawer.tsx');
18
- const assist = read('adminWww/js/eos-assistant.js');
19
- const knowledge = read('src/lib/chat/assistantKnowledge.ts');
20
- const io = json('io-package.json');
21
-
22
- for (const code of [mainSource, mainBuilt]) {
23
- for (const marker of [
24
- "LEGACY_BACKUP_ADAPTER_NAME = 'backitup'", 'shouldHideLegacyBackupFromNonAdmins',
25
- 'getLegacyBackupAclObjectIds', 'ensureLegacyBackupVisibleOnlyToAdmins',
26
- 'EOS ACL guard restricted internal', '/^system\\.adapter\\.(?:admin|backitup)(?:\\.|$)/',
27
- '/^(?:admin|backitup)\\.\\d+(?:\\.|$)/', 'internal Service reserve is Admin/Service-only',
28
- ]) if (!code.includes(marker)) fail(`backend reserve marker missing: ${marker}`);
29
- }
30
- for (const code of [webSource, webBuilt]) {
31
- for (const marker of [
32
- "LEGACY_BACKUP_ADAPTER_NAME = 'backitup'", "CUSTOMER_BACKUP_ADAPTER_NAMES = ['nexowatt-backup', 'eos-backup']",
33
- 'nexowattBackup: true', "internalBackupReserve: role === 'admin'", 'hideLegacyBackupFromNonAdmins',
34
- 'legacyBackupAdapter', 'customerBackupAdapters',
35
- ]) if (!code.includes(marker)) fail(`web reserve marker missing: ${marker}`);
36
- }
37
- for (const marker of [
38
- 'isOfficialAdminTab', 'isOfficialBackupTab', 'isOfficialReserveTab', 'isCustomerBackupTab',
39
- 'system.adapter.backitup', 'tab-backitup', 'nexowatt-backup', 'eos-backup',
40
- 'exact visible instance ID', 'data-eos-official-reserve-hidden', 'Reused virtual rows must be unhidden',
41
- ]) if (!role.includes(marker)) fail(`role UI reserve marker missing: ${marker}`);
42
- for (const marker of ['isOfficialReserveTab', 'isCustomerBackupTab', 'backitup', 'nexowatt-backup']) {
43
- if (!boot.includes(marker)) fail(`bootstrap reserve marker missing: ${marker}`);
44
- }
45
- for (const marker of ['System-Notfallsicherung', 'NexoWatt Sicherung', '^tab-backitup', 'nexowatt-backup|eos-backup']) {
46
- if (!drawer.includes(marker)) fail(`Drawer reserve marker missing: ${marker}`);
47
- }
48
- if (!assist.includes('NexoWatt Backup') && !assist.includes('Sicherungsstatus')) fail('EOS Assist runtime lacks backup-system context');
49
- if (!knowledge.includes('NexoWatt Backup') || !knowledge.includes('Admin/Service')) fail('EOS Assist knowledge lacks role-aware backup context');
50
- if (io.native?.eosHideLegacyBackupFromNonAdmins !== true) fail('eosHideLegacyBackupFromNonAdmins must default to true');
51
- if (io.native?.nexowattHideLegacyBackupFromNonAdmins !== true) fail('nexowattHideLegacyBackupFromNonAdmins must default to true');
52
- const reserve = (io.native?.eosProtectedAdapters || []).find(entry => entry.adapter === 'backitup');
53
- if (!reserve?.enabled || !/Notfallreserve/i.test(String(reserve.note))) fail('backitup reserve is not clearly marked in the protected adapter defaults');
54
- if (role.includes("/^tab-(?:admin|backitup|nexowatt-backup)/")) fail('customer backup must not be grouped with internal reserves');
55
-
56
- if (bad) process.exit(1);
57
- console.log('[NexoWatt EOS internal reserve] OK');
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const fs = require('fs');
5
- const path = require('path');
6
-
7
- const root = path.resolve(__dirname, '..');
8
- const read = rel => fs.readFileSync(path.join(root, rel), 'utf8');
9
- let bad = false;
10
- const fail = message => {
11
- console.error(`[NexoWatt EOS login layout] ${message}`);
12
- bad = true;
13
- };
14
-
15
- const css = read('adminWww/css/nexowatt-native-shell.css');
16
- const sourceCss = read('src-admin/public/css/nexowatt-native-shell.css');
17
- const login = read('src-admin/src/login/Login.tsx');
18
- const bootstrap = read('adminWww/js/eos-role-bootstrap.js');
19
- const index = read('adminWww/index.html');
20
- const buildInfo = JSON.parse(read('NEXOWATT_EOS_BUILD_INFO.json'));
21
- const shellTag = String(buildInfo.shellCacheTag || buildInfo.shellCacheVersion || '');
22
-
23
- if (css !== sourceCss) fail('login CSS source/build drift');
24
- if (!css.includes('outer frame is decorative only')) fail('decorative compact-frame contract is missing');
25
- if (css.includes('html.eos-login .MuiPaper-root:has(#username)')) fail('broad :has selector still styles the outer login Paper');
26
-
27
- const outer = css.match(/html\.eos-login main\.MuiPaper-root\s*\{([\s\S]*?)\n\}/)?.[1] || '';
28
- for (const marker of ['position: relative', 'width: 100%', 'min-height: 100vh', 'place-items: center', 'background: transparent !important', 'box-shadow: none !important']) {
29
- if (!outer.includes(marker)) fail(`transparent viewport host rule missing: ${marker}`);
30
- }
31
- const decorative = css.match(/html\.eos-login main\.MuiPaper-root::before\s*\{([\s\S]*?)\n\}/)?.[1] || '';
32
- for (const marker of ["content: ''", 'width: min(390px, calc(100vw - 24px))', 'height: min(480px, calc(100vh - 24px))', 'transform: translate(-50%, -50%)', 'pointer-events: none']) {
33
- if (!decorative.includes(marker)) fail(`decorative rear frame rule missing: ${marker}`);
34
- }
35
- const compactBlocks = [...css.matchAll(/html\.eos-login[^\{]*eos-login-card-modern[^\{]*\{([\s\S]*?)\n\}/g)].map(match => match[1]);
36
- if (!compactBlocks.length) fail('compact login card CSS block missing');
37
- for (const block of compactBlocks) {
38
- if (/overflow\s*:\s*auto\s*!important/.test(block) || /overflow-y\s*:\s*(?:auto|scroll)/.test(block)) {
39
- fail('compact login card still creates an internal scrollbar');
40
- }
41
- }
42
- for (const marker of [
43
- 'html.eos-login main.MuiPaper-root > .eos-login-card-modern',
44
- 'html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username)',
45
- 'html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password)',
46
- 'width: min(334px, calc(100vw - 56px)) !important',
47
- 'height: min(424px, calc(100vh - 56px)) !important',
48
- 'max-height: none !important',
49
- 'overflow: hidden !important',
50
- 'scrollbar-width: none !important',
51
- '::-webkit-scrollbar',
52
- ]) if (!css.includes(marker)) fail(`inner compact card rule missing: ${marker}`);
53
- if (!css.includes('.eos-login-first-status:empty { display: none; min-height: 0; margin: 0; }')) fail('empty first-login status still reserves vertical space');
54
- if (!login.includes('Keep the familiar compact login page')) fail('native Login source lacks compact-page contract');
55
- if (!login.includes("overflowY: 'hidden'")) fail('native Login paper still enables vertical scrolling');
56
- if (login.includes('eos-login-role-selector-native') || login.includes('data-eos-account=')) fail('native Login source still renders role-selector buttons');
57
- if (!bootstrap.includes('compact normal-login first activation')) fail('runtime compact first-login contract missing');
58
- if (!bootstrap.includes("card.querySelectorAll('.eos-login-role-selector').forEach(element => element.remove())")) fail('runtime does not remove stale role-selector surfaces');
59
- if (/data-eos-account=|selector\.innerHTML/.test(bootstrap)) fail('runtime still injects a second role-selector panel');
60
- if (!shellTag || !index.includes(`nexowatt-native-shell.css?v=${shellTag}`)) fail('login CSS cache key is not aligned with build information');
61
- if (bad) process.exit(1);
62
- console.log('[NexoWatt EOS login layout] OK');