import { expect, type Page } from '@playwright/test'; import { test } from '../fixtures/ids'; import { CleanupRegistry } from '../fixtures/cleanup'; import { adminApi } from '../fixtures/api'; // Phase B7 — Profile + API Keys (/admin/profile). Covers the // mint/reveal/revoke flow, the app-binding mutual-exclusion guard, // and adversarial inputs. const cleanup = new CleanupRegistry(); test.afterEach(async () => { await cleanup.run(); }); async function createApp(slug: string): Promise { const api = await adminApi(); try { const res = await api.post('/api/v1/admin/apps', { data: { slug, name: slug } }); expect(res.ok()).toBe(true); return ((await res.json()) as { id: string }).id; } finally { await api.dispose(); } } async function openMintForm(page: Page): Promise { await page.goto('/admin/profile'); await page.getByRole('button', { name: /\+ Mint API key/ }).click(); } async function registerKeyCleanupByName(name: string): Promise { const api = await adminApi(); try { const res = await api.get('/api/v1/admin/api-keys'); const all = (await res.json()) as Array<{ id: string; name: string }>; const k = all.find((x) => x.name === name); if (k) cleanup.apiKey(k.id); } finally { await api.dispose(); } } test.describe('B7 profile + API keys', () => { test('mint instance-wide key: reveal → ack → key appears in list', async ({ page }) => { const name = `e2e-mint-${Date.now()}`; await openMintForm(page); await page.locator('form.mint').getByPlaceholder('e.g. ci-deploy').fill(name); // Pick a non-instance scope so we don't need to worry about // mutual exclusion here. The scope-chip is a