/** * SDK Test Runner — Domain: admin * * Tests kernel admin endpoints. Requires admin role. * Extension admin endpoints (configs, models, tasks, routing, * providers/health, channels/archived, projects, cluster) belong * in package runners, not here. */ (function () { 'use strict'; var T = window.SDKR; if (!T) return; sw.testing.suite('sdk/admin', async function (s) { // Guard: skip if not admin if (!window.sw || !sw.isAdmin) { s.test('guard: skip — not admin', async function (t) { T.assert(true, 'skipped (user is not admin)'); }); return; } // ── Users ── s.test('users: sw.api.admin.users.list()', async function (t) { var result = await T.dualTest( function () { return sw.api.admin.users.list(); }, { method: 'GET', path: '/admin/users' }, function (r) { // KNOWN: backend returns {users: [...]} not {data: [...]} var arr = r; if (r && r.users) arr = r.users; if (r && r.data) arr = r.data; T.assert(Array.isArray(arr), 'expected array (maybe wrapped in non-standard key)'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Settings ── s.test('settings: sw.api.admin.settings.get()', async function (t) { var result = await T.dualTest( function () { return sw.api.admin.settings.get(); }, { method: 'GET', path: '/admin/settings' }, function (r) { T.assert(typeof r === 'object', 'expected object'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Teams ── s.test('teams: GET /admin/teams (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/teams'); }, { method: 'GET', path: '/admin/teams' }, function (r) { T.assert(r && Array.isArray(r.data), 'expected { data: [...] }'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Groups ── s.test('groups: GET /admin/groups (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/groups'); }, { method: 'GET', path: '/admin/groups' }, function (r) { T.assert(r && Array.isArray(r.data), 'expected { data: [...] }'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Packages ── s.test('packages: sw.api.admin.packages.list()', async function (t) { var result = await T.dualTest( function () { return sw.api.admin.packages.list(); }, { method: 'GET', path: '/admin/packages' }, function (r) { T.assert(Array.isArray(r) || (r && Array.isArray(r.data)), 'expected array'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Surfaces ── s.test('surfaces: sw.api.admin.surfaces.list()', async function (t) { var result = await T.dualTest( function () { return sw.api.admin.surfaces.list(); }, { method: 'GET', path: '/admin/packages' }, function (r) { var arr = T.unwrapList(r); T.assert(arr.length >= 0, 'expected list'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Extensions ── s.test('extensions: sw.api.admin.extensions.list()', async function (t) { var result = await T.dualTest( function () { return sw.api.admin.extensions.list(); }, { method: 'GET', path: '/admin/extensions' }, function (r) { var arr = T.unwrapList(r); T.assert(arr.length >= 0, 'expected list'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Permissions ── s.test('permissions: GET /admin/permissions (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/permissions'); }, { method: 'GET', path: '/admin/permissions' }, function (r) { T.assert(r && r.permissions, 'expected permissions key'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Audit ── s.test('audit: GET /admin/audit (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/audit'); }, { method: 'GET', path: '/admin/audit' }, function (r) { T.assert(r && Array.isArray(r.data), 'expected { data: [...] }'); T.assert(typeof r.total === 'number', 'expected total'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); s.test('audit: GET /admin/audit/actions (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/audit/actions'); }, { method: 'GET', path: '/admin/audit/actions' }, function (r) { T.assert(r && r.actions, 'expected actions key'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Metrics (v0.6.4+) ── s.test('metrics: GET /admin/metrics (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/metrics'); }, { method: 'GET', path: '/admin/metrics' }, function (r) { T.assert(typeof r === 'object', 'expected object'); T.assertHasKey(r, 'runtime', 'metrics'); T.assertHasKey(r, 'database', 'metrics'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Storage ── s.test('storage: sw.api.admin.storage.status()', async function (t) { var result = await T.dualTest( function () { return sw.api.admin.storage.status(); }, { method: 'GET', path: '/admin/storage/status' }, function (r) { T.assert(typeof r === 'object', 'expected object'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Vault ── s.test('vault: sw.api.admin.vault.status()', async function (t) { if (!window.sw || !sw.isAdmin) { t.warn('SKIP: not admin'); return; } // Vault may not be configured — try raw to check availability var available = false; try { var token = await T.getAuthToken(); var resp = await fetch(T.base + '/api/v1/admin/vault/status', { method: 'GET', headers: { 'Authorization': 'Bearer ' + token }, credentials: 'same-origin' }); available = resp.ok; } catch (e) { /* not available */ } if (!available) { t.warn('SKIP: vault not configured'); return; } var result = await T.dualTest( function () { return sw.api.admin.vault.status(); }, { method: 'GET', path: '/admin/vault/status' }, function (r) { T.assert(typeof r === 'object', 'expected object'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); // ── Backups (v0.6.1+) ── s.test('backups: GET /admin/backups (raw)', async function (t) { var result = await T.dualTest( function () { return sw.api.get('/api/v1/admin/backups'); }, { method: 'GET', path: '/admin/backups' }, function (r) { var arr = T.unwrapList(r); T.assert(arr.length >= 0, 'expected backup list'); } ); if (result.verdict === 'PASS') return; if (result.verdict === 'SDK_BUG') t.assert.ok(false, 'SDK_BUG: ' + result.sdkErr); if (result.verdict === 'ICD_BUG') t.assert.ok(false, 'ICD_BUG: ' + result.rawErr); if (result.verdict === 'SHAPE_BUG') t.warn('SHAPE_BUG: ' + result.sdkErr); }); }); })();