test(admin): qualify the users table alignment
@@ -7,7 +7,7 @@ Owner addendum received 9 November 2026. Source `E:/Storage/Projects/Active/temp
|
||||
| Admin information isolation | First slice published on `codex/security-offline-preflight` at `ecadc29b`. Reproduced and removed imported mail subjects from the Admin Audit projection. 62 selected offline tests passed, including owner-bound notices and operations. | Integrated security, remaining delivery paths, broader minimisation and deployment checks remain separate. |
|
||||
| Discover Jobs | [Search-first layout](visual-correction/DISCOVERY_SEARCH_FIRST.md) moves the query above filters and qualifies the existing NAV request, keyboard submit and source disclosure. | Expose new filters, map and multilingual suggestions only with qualified data and the existing GJ architecture. Mobile filter drawer and focused detail remain open. |
|
||||
| Applications | [Title-first rows and explicit bulk mode](visual-correction/APPLICATION_SELECTION_REVIEW.md) qualified at 36 configurations. | Secondary action consolidation and final native/visual review remain open. |
|
||||
| Admin Users and Audit | Verify row alignment and review existing read metadata, available filters and expandable records. The MFA proposal is in `docs/security/MFA_RECOVERY_PROPOSAL.md` on the security branch. | 2FA recovery and private support access require explicit owner approval of their technical and privacy designs. |
|
||||
| Admin Users and Audit | [User row alignment](visual-correction/ADMIN_USER_ALIGNMENT_REVIEW.md) passed 36 configurations. Review existing read metadata, available filters and expandable records next. The MFA proposal is in `docs/security/MFA_RECOVERY_PROPOSAL.md` on the security branch. | 2FA recovery and private support access require explicit owner approval of their technical and privacy designs. |
|
||||
| Job Correspondence | Continue inbox layout, mailbox-status presentation and existing explicit consent flow. | Provider verification, restricted scopes, multiple-account persistence and retention decisions retain their gates. Signing in grants no mailbox access. |
|
||||
| System Status | Review current operational owners and distinguish current, stale and unavailable readings. Keep the CV benchmark while qualification depends on it. | Predefined diagnostics require isolated execution, role checks and audit. Live diagnostics, workers and arbitrary command execution are outside this scope. |
|
||||
| Terminology | “Prepare application” / “Klargjør søknaden” is visible in the scoped EN/NB application checks. | Continue broader terminology and European catalogue review. |
|
||||
|
||||
@@ -60,3 +60,6 @@ Secondary checkpoint7aa54bff1fe376b798922b9da75feafa202dbb76 is published/remote
|
||||
Active bounded fix (uncommitted): AI privacy Save now invokes an optional refresh callback; App rereads /auth/me and updates only same-owner, validated plan/entitlements without resetting authResolved or dispatching auth-changed. Lifetime/session/sequence guards reject stale completion; general auth refresh invalidates the availability lane. Card distinguishes saved preferences from refresh failure and preserves its mounted draft.39 selected tests/three suites,types/lint/build passed; browser pilot is being corrected to respect existing API identity-mismatch invalidation (session reset, not an inline warning). Targeted malformed-entitlement and same-owner/no-reload journeys must pass before publication. No backend/model/provider changes. Do not discard the active regression/fix files or claim the display gap closed until its actual evidence is qualified.
|
||||
|
||||
4 November successor: the owner added global flat visual correction and a whole-application definition of done. These extend approved IM10; earlier functional approvals remain evidence, not visual parity. Shared compact shell/open CV studio/flat continuous Settings sections are implemented. Mounted availability gap now has16 successful controlled journeys/64 scans with node/draft retention, malformed-grant rejection and wrong-identity session reset. CV visual matrix:36 configurations/108 scans/captures across all nine required widths, EN/NB and themes. Failed NB notice/tablet overlap attempts retained and fixed. Types/lint/build/census passed; independent source review found no actionable findings. The full34-route visual review, connected workflows, human/device/native language and final visual approval remain OPEN. See visual-correction/VALIDATION.md and DISCREPANCIES.md. Next eligible work: remaining route review and bounded remediation, beginning six secondary routes. Do not request final IM10 acceptance yet.
|
||||
# Admin Users alignment checkpoint
|
||||
|
||||
10 November 2026. Runtime `dddec043664cd1e65f93469e112c92f4794b8821` passed 12 selected native tests, types, lint, export build and 36 controlled responsive accessibility scans. See [alignment review](visual-correction/ADMIN_USER_ALIGNMENT_REVIEW.md).
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Admin Users row alignment
|
||||
|
||||
Runtime `dddec043664cd1e65f93469e112c92f4794b8821`. The existing grid cells now use flex alignment to centre the email, username, roles, confirmation status and actions within the row. The phone layout keeps the existing stacked cards.
|
||||
|
||||
The retained 1440 px EN light baseline showed a 14 px maximum vertical offset. The successor measured at most 0.5 px across all 20 grid configurations. The other 16 configurations checked the phone layout. All 36 configurations across nine widths, EN/NB and both themes passed the layout checks and scoped axe scans. Both the 1440 px EN light and 320 px NB dark screenshots were visually reviewed. The pilot overlaps the matrix.
|
||||
|
||||
12 Admin Users tests, type-check, full lint, harness lint and the export build passed. The browser fixtures preserved the disabled remove-admin and delete controls for the final administrator. They recorded zero writes or page errors and 36 unavailable company reads outside the Users route's data. User creation, password reset delivery, 2FA status, role mutations and native device review are outside this evidence.
|
||||
@@ -36,6 +36,7 @@ Owner correction: 3 November 2026. This register extends IM10 and the original 3
|
||||
| V26 | Embedded Gmail review counts | One thread/suggestion renders “1 candidate threads” and “1 suggested jobs” | RESOLVED in `e8e7d839` | EN/NB singular cases, zero/plural and live language switching verified. See [review count wording](MAIL_REVIEW_COUNTS.md) |
|
||||
| V27 | Public homepage baseline | Earlier mockups, missing landmarks and crawlable locale content, anonymous preference request rejected | OPEN in LAUNCH-SITE-01 | [Rendered baseline](LANDING_BASELINE_REVIEW.md) captures mobile, tablet and desktop without choosing a launch design |
|
||||
| V28 | Application list | Ordinary rows show permanent selection controls and company before the role | RESOLVED in `1246994c` | [Selection review](APPLICATION_SELECTION_REVIEW.md) covers title-first hierarchy and the explicit mode. Secondary action consolidation remains open. |
|
||||
| V29 | Admin Users | Row details sit above the centre of the action controls | RESOLVED in `dddec043` | [Alignment review](ADMIN_USER_ALIGNMENT_REVIEW.md) records the before and after geometry and phone layout. |
|
||||
|
||||
The owner-approved design foundation remains original A1 dashboard, D1 visual system, B1 tracking, editor left / preview right, application context right, desktop sidebar and hybrid mobile navigation. No controls, imports, revisions, permissions or provider rights may be removed to obtain visual simplicity.
|
||||
|
||||
|
||||
@@ -229,9 +229,9 @@
|
||||
"AdminUsersPage"
|
||||
],
|
||||
"visualStatus": "MEANINGFUL_USER_FORM_TABLE_BOUNDARIES_RETAINED",
|
||||
"afterStatus": "PASSED:36 configurations /324 admin states combined; current last-admin disabled actions only; creation/dialog/error states remain open",
|
||||
"afterStatus": "PASSED:36 configurations for aligned grid rows or phone cards, with final-administrator protections; creation/dialog/error states remain open",
|
||||
"functionalCriteria": "Original preservation register retained; no capability acceptance promotion",
|
||||
"evidence": "ADMIN_HEADINGS_REVIEW.md; evidence/admin-headings/BROWSER.json; prior ADMIN_REVIEW.md"
|
||||
"evidence": "ADMIN_USER_ALIGNMENT_REVIEW.md; evidence/admin-user-alignment/BROWSER.json; earlier ADMIN_HEADINGS_REVIEW.md and ADMIN_REVIEW.md"
|
||||
},
|
||||
{
|
||||
"route": "/admin/system",
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"screens": [
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"state": "last-admin",
|
||||
"capture": "full page at top",
|
||||
"violations": []
|
||||
}
|
||||
],
|
||||
"journeys": [
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"cellOffsets": [
|
||||
{
|
||||
"field": "email",
|
||||
"offset": 0.5
|
||||
},
|
||||
{
|
||||
"field": "userName",
|
||||
"offset": 0.375
|
||||
},
|
||||
{
|
||||
"field": "roles",
|
||||
"offset": 0.5
|
||||
},
|
||||
{
|
||||
"field": "emailConfirmed",
|
||||
"offset": 0.5
|
||||
},
|
||||
{
|
||||
"field": "actions",
|
||||
"offset": 0.5
|
||||
}
|
||||
],
|
||||
"lastAdminActionsDisabled": "PASS"
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"unexpectedWrites": [],
|
||||
"exportDenials": [],
|
||||
"unavailableReads": [
|
||||
"/api/companies"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com"
|
||||
],
|
||||
"limits": [
|
||||
"Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.",
|
||||
"Only the Users table alignment, mobile layout and last-administrator disabled actions are exercised.",
|
||||
"No real credentials, provider activation, model, native device, integrated security, production or release acceptance."
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"screens": [
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"state": "last-admin",
|
||||
"capture": "full page at top",
|
||||
"violations": []
|
||||
}
|
||||
],
|
||||
"journeys": [
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"cellOffsets": [
|
||||
{
|
||||
"field": "email",
|
||||
"offset": -13.5
|
||||
},
|
||||
{
|
||||
"field": "userName",
|
||||
"offset": -14
|
||||
},
|
||||
{
|
||||
"field": "roles",
|
||||
"offset": -9.5
|
||||
},
|
||||
{
|
||||
"field": "emailConfirmed",
|
||||
"offset": -12.421875
|
||||
},
|
||||
{
|
||||
"field": "actions",
|
||||
"offset": 0.5
|
||||
}
|
||||
],
|
||||
"lastAdminActionsDisabled": "PASS"
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"unexpectedWrites": [],
|
||||
"exportDenials": [],
|
||||
"unavailableReads": [
|
||||
"/api/companies"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com"
|
||||
],
|
||||
"limits": [
|
||||
"Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.",
|
||||
"System and audit populated states are synthetic read fixtures; no probe, maintenance, settings save, undo, restore or provider action executed.",
|
||||
"No real credentials, provider activation, model, native device, integrated security, production or release acceptance."
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 57 KiB |
@@ -43,7 +43,7 @@ const screens = [
|
||||
{name:'Mail label counts',reference:'correspondence',folder:'mail-labels',state:'label-count',source:'cd116ab8',scope:'Singular text at all nine widths; native singular/plural/live-locale regression passed. No writes or repeated send workflow.'},
|
||||
{name:'Mail review suggestion',reference:'correspondence',folder:'mail-review-counts',state:'review-counts',source:'e8e7d839',scope:'Fixture suggestion with corrected singular thread, job and message counts. Review actions were not executed.'},
|
||||
{name:'Mail draft conflict',reference:'correspondence',folder:'mail-recovery',state:'draft-conflict',source:'c7e8627c',scope:'A controlled 409 preserves unsaved text and shows the conflict warning. No send request.'},
|
||||
{name:'Administration users',reference:'admin',folder:'admin-headings',state:'last-admin',source:'c7e8627c',scope:'Existing last-administrator disabled actions and meaningful user/form boundaries retained. Synthetic reads only; no user mutations.'},
|
||||
{name:'Administration users',reference:'admin',folder:'admin-user-alignment',state:'last-admin',source:'dddec043',scope:'User fields and actions align on desktop. Phone cards retain their stacked layout and final-administrator protections.'},
|
||||
{name:'Administration audit',reference:'admin',folder:'audit-date',state:'audit-populated',source:'2dc8fe4c',scope:'Readable timestamp and compact fixture row in the existing scrollable table. No undo or restore executed.'},
|
||||
{name:'Administration system',reference:'admin',folder:'admin-headings',state:'system-normal',source:'c7e8627c',scope:'Open diagnostic sections and unboxed metrics; every status is synthetic, with AI disabled. No live health claim.'},
|
||||
{name:'Administration benchmark',reference:'admin',folder:'admin-headings',state:'system-findings',source:'c7e8627c',scope:'Divided synthetic findings/weak files without nested panels/shadows. Unapproved fixture; no benchmark execution or engine acceptance.'},
|
||||
|
||||
@@ -11,9 +11,11 @@ const accountOnly = Boolean(process.env.A3_ACCOUNT_FLAT);
|
||||
const adminOnly = Boolean(process.env.A3_ADMIN_FLAT);
|
||||
const adminHeadings = Boolean(process.env.A3_ADMIN_HEADINGS);
|
||||
const auditDateOnly = Boolean(process.env.A3_AUDIT_DATE);
|
||||
const userAlignmentOnly = Boolean(process.env.A3_ADMIN_USER_ALIGNMENT);
|
||||
assert.ok(!adminHeadings || adminOnly, 'Heading qualification uses the Admin fixtures.');
|
||||
assert.ok(!auditDateOnly || (adminOnly && !adminHeadings), 'Audit timestamp qualification uses its own scope.');
|
||||
const out = path.resolve(import.meta.dirname, auditDateOnly ? '../../docs/ui-modernisation/visual-correction/evidence/audit-date' : adminHeadings ? '../../docs/ui-modernisation/visual-correction/evidence/admin-headings' : adminOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-flat' : accountOnly ? '../../docs/ui-modernisation/visual-correction/evidence/account-flat' : '../../docs/ui-modernisation/evidence/account-admin/browser');
|
||||
assert.ok(!userAlignmentOnly || (adminOnly && !adminHeadings && !auditDateOnly), 'Admin Users alignment uses its own scope.');
|
||||
const out = path.resolve(import.meta.dirname, userAlignmentOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-user-alignment' : auditDateOnly ? '../../docs/ui-modernisation/visual-correction/evidence/audit-date' : adminHeadings ? '../../docs/ui-modernisation/visual-correction/evidence/admin-headings' : adminOnly ? '../../docs/ui-modernisation/visual-correction/evidence/admin-flat' : accountOnly ? '../../docs/ui-modernisation/visual-correction/evidence/account-flat' : '../../docs/ui-modernisation/evidence/account-admin/browser');
|
||||
fs.mkdirSync(out, { recursive: true });
|
||||
const report = { screens: [], journeys: [], errors: [], unexpectedWrites: [], exportDenials: [], unavailableReads: [], blockedExternal: [] };
|
||||
const browser = await chromium.launch();
|
||||
@@ -21,7 +23,7 @@ const processingOnly = Boolean(process.env.A3_PROCESSING_ONLY);
|
||||
assert.ok(!(processingOnly && accountOnly), 'Account and processing qualification are distinct scopes.');
|
||||
assert.ok(!adminOnly || !(processingOnly || accountOnly), 'Admin qualification is a distinct scope.');
|
||||
try {
|
||||
const configurations = process.env.A3_PILOT ? (auditDateOnly ? [[768, 'nb', 'dark']] : adminOnly ? [[320, 'en', 'light'], [1440, 'en', 'light']] : [[320, 'en', 'light']]) : (accountOnly || adminOnly ? [320, 360, 390, 430, 768, 1024, 1280, 1440, 1920] : [320, 390, 768, 1440]).flatMap(width => ['en', 'nb'].flatMap(language => ['light', 'dark'].map(mode => [width, language, mode])));
|
||||
const configurations = process.env.A3_PILOT ? (userAlignmentOnly ? [[1440, 'en', 'light']] : auditDateOnly ? [[768, 'nb', 'dark']] : adminOnly ? [[320, 'en', 'light'], [1440, 'en', 'light']] : [[320, 'en', 'light']]) : (accountOnly || adminOnly ? [320, 360, 390, 430, 768, 1024, 1280, 1440, 1920] : [320, 390, 768, 1440]).flatMap(width => ['en', 'nb'].flatMap(language => ['light', 'dark'].map(mode => [width, language, mode])));
|
||||
for (const [width, language, mode] of configurations) {
|
||||
console.log(`Checking ${width}/${language}/${mode}`);
|
||||
const t = key => { assert.ok(translations[language][key], key); return translations[language][key]; };
|
||||
@@ -87,6 +89,26 @@ try {
|
||||
await expect(page.getByRole('heading', { name: t(title), exact: true, level: 1 })).toBeVisible();
|
||||
await expect(page.getByText(t(subtitle), { exact: true })).toBeVisible();
|
||||
};
|
||||
if (userAlignmentOnly) {
|
||||
await page.goto('http://localhost:4338/admin/users');
|
||||
await expect(page.getByRole('button', { name: t('adminUsersRemoveAdmin'), exact: true })).toBeDisabled();
|
||||
await expect(page.getByRole('button', { name: t('adminUsersDelete'), exact: true })).toBeDisabled();
|
||||
await scan('last-admin');
|
||||
const grid = page.getByRole('grid');
|
||||
const cells = width >= 768 ? await grid.getByRole('gridcell').evaluateAll(nodes => nodes.map(cell => {
|
||||
const cellBounds = cell.getBoundingClientRect();
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(cell);
|
||||
const content = cell.firstElementChild?.getBoundingClientRect() ?? range.getBoundingClientRect();
|
||||
return { field: cell.dataset.field, offset: content.y + content.height / 2 - (cellBounds.y + cellBounds.height / 2) };
|
||||
})) : [];
|
||||
report.journeys.push({ width, language, mode, cellOffsets: cells, lastAdminActionsDisabled: 'PASS' });
|
||||
if (width >= 768) {
|
||||
assert.equal(cells.length, 5);
|
||||
assert.ok(cells.every(cell => Math.abs(cell.offset) < 3), `Admin user cell content is misaligned: ${JSON.stringify(cells)}`);
|
||||
} else await expect(grid).toHaveCount(0);
|
||||
await context.close(); continue;
|
||||
}
|
||||
if (auditDateOnly) {
|
||||
populatedAudit = true;
|
||||
await page.goto('http://localhost:4338/admin/audit');
|
||||
@@ -172,10 +194,10 @@ try {
|
||||
}
|
||||
report.journeys.push({ width, language, mode, draftPreservedAcrossKeyboardSections: processingOnly || adminOnly ? 'NOT RUN' : 'PASS', revocationAndDeletionCancelled: processingOnly || adminOnly ? 'NOT RUN' : 'PASS', recentExportDenial: processingOnly || adminOnly ? 'NOT RUN' : 'PASS', lastAdminActionsDisabled: processingOnly || accountOnly ? 'NOT RUN' : 'PASS', processingKeyboardAndOwnerLink: accountOnly ? 'NOT RUN' : 'PASS', processingFilterLabelsAndDurationGeometry: accountOnly ? 'NOT RUN' : 'PASS', populatedAdminReadStates: adminOnly ? 'PASS' : 'NOT RUN' }); await context.close();
|
||||
}
|
||||
assert.equal(report.screens.length, configurations.length * (auditDateOnly || processingOnly ? 1 : accountOnly ? 7 : adminOnly ? 9 : 8)); assert.equal(report.journeys.length, configurations.length); assert.equal(report.exportDenials.length, processingOnly || adminOnly ? 0 : configurations.length);
|
||||
assert.equal(report.screens.length, configurations.length * (userAlignmentOnly || auditDateOnly || processingOnly ? 1 : accountOnly ? 7 : adminOnly ? 9 : 8)); assert.equal(report.journeys.length, configurations.length); assert.equal(report.exportDenials.length, processingOnly || adminOnly ? 0 : configurations.length);
|
||||
assert.deepEqual(report.errors, []); assert.deepEqual(report.unexpectedWrites, []); assert.ok(report.blockedExternal.every(origin => origin === 'https://fonts.googleapis.com'));
|
||||
console.log(`PASS:${report.journeys.length} controlled journeys,${report.screens.length} axe scans/captures; no mutation requests.`);
|
||||
} finally {
|
||||
fs.writeFileSync(path.join(out, processingOnly ? 'PROCESSING.json' : process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.', auditDateOnly ? 'Only the populated audit table, timestamp geometry and keyboard scrolling are exercised.' : adminOnly ? 'System and audit populated states are synthetic read fixtures; no probe, maintenance, settings save, undo, restore or provider action executed.' : 'System monitor is unavailable and audit empty; detailed success/action scenarios are unit tests, not live qualification.', 'No real credentials, provider activation, model, native device, integrated security, production or release acceptance.'] }, null, 2));
|
||||
fs.writeFileSync(path.join(out, processingOnly ? 'PROCESSING.json' : process.env.A3_PILOT ? 'PILOT.json' : 'BROWSER.json'), JSON.stringify({ ...report, limits: ['Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.', userAlignmentOnly ? 'Only the Users table alignment, mobile layout and last-administrator disabled actions are exercised.' : auditDateOnly ? 'Only the populated audit table, timestamp geometry and keyboard scrolling are exercised.' : adminOnly ? 'System and audit populated states are synthetic read fixtures; no probe, maintenance, settings save, undo, restore or provider action executed.' : 'System monitor is unavailable and audit empty; detailed success/action scenarios are unit tests, not live qualification.', 'No real credentials, provider activation, model, native device, integrated security, production or release acceptance.'] }, null, 2));
|
||||
await browser.close();
|
||||
}
|
||||
|
||||