[verified] add admin AI provider settings UI
This commit is contained in:
@@ -44,25 +44,25 @@ check('dom.operator-markers', 'operator-critical DOM markers are present', has(h
|
||||
'id="loginScreen"', 'id="dashboardShell"', 'id="explorer"', 'id="detailPanel"',
|
||||
'id="reviewQueueCount"', 'id="jobsList"', 'id="sourcesList"', 'id="pipelineBoard"',
|
||||
'id="interactionState"', 'id="pipelineReport"', 'id="suppressionState"',
|
||||
'id="providerPolicyPanel"', 'id="scoreRulesPanel"', 'id="scoreDistributionPanel"'
|
||||
'id="providerPolicyPanel"', 'id="aiProviderSettings"', 'id="aiProviderForm"', 'id="aiProviderStatus"', 'id="scoreRulesPanel"', 'id="scoreDistributionPanel"'
|
||||
]));
|
||||
check('dom.safety-markers', 'safety and approval sections have stable smoke markers', [
|
||||
'saved-views', 'review-queue', 'crm-pipeline', 'crm-interactions', 'crm-reports',
|
||||
'suppression-center', 'outreach-provider-policy', 'score-rules', 'score-distribution'
|
||||
'suppression-center', 'outreach-provider-policy', 'ai-provider-settings', 'score-rules', 'score-distribution'
|
||||
].every(marker => markers.has(marker)));
|
||||
check('dom.required-controls', 'operator controls have stable IDs', [
|
||||
'loginEmail', 'loginPassword', 'logoutBtn', 'nextPageBtn', 'bulkVerifyBtn', 'bulkRejectBtn',
|
||||
'savedFilterForm', 'pipelineViewToggle', 'interactionForm', 'suppressionForm', 'outreachPolicyRefreshBtn'
|
||||
'savedFilterForm', 'pipelineViewToggle', 'interactionForm', 'suppressionForm', 'outreachPolicyRefreshBtn', 'aiProviderRefreshBtn', 'testAiProviderBtn', 'saveAiProviderBtn'
|
||||
].every(id => htmlIds.has(id)) && has(js, [
|
||||
'scanWebsiteBtn', 'extractContactsBtn', 'recalculateScoreBtn', 'generateAiSuggestionBtn', 'createOutreachDraftBtn'
|
||||
]));
|
||||
|
||||
check('css.responsive', 'responsive CSS is present for mobile operator layouts',
|
||||
/@media\s*\(max-width\s*:\s*700px\)/.test(css) &&
|
||||
has(css, ['.saved-view-controls', '.website-scan-grid', '.crm-two-col', '.reports-grid', '.outreach-panel']));
|
||||
has(css, ['.saved-view-controls', '.website-scan-grid', '.crm-two-col', '.reports-grid', '.outreach-panel', '.ai-provider-grid']));
|
||||
check('css.layout-contracts', 'critical layout selectors are defined', has(css, [
|
||||
'.app-shell', '.sidebar', '.workspace-grid', '.table-scroll', '.pipeline-board',
|
||||
'.jobs-grid', '.sources-grid', '.score-config-row', '.provider-policy-row'
|
||||
'.jobs-grid', '.sources-grid', '.score-config-row', '.provider-policy-row', '.ai-provider-status-row'
|
||||
]));
|
||||
|
||||
check('safety.no-send-copy', 'persistent no-send and approval safety copy is present', has(`${html}\n${js}`, [
|
||||
@@ -79,6 +79,10 @@ check('safety.no-secrets', 'frontend source has no obvious hardcoded secrets',
|
||||
));
|
||||
check('safety.approval-gated', 'approval is explicitly human-confirmed and non-delivering',
|
||||
has(js, ['window.confirm', 'human_approval:true', 'send:false', 'Approval does not send a message.']));
|
||||
check('ai-provider.write-only', 'AI provider credentials are write-only and never browser-persisted',
|
||||
has(`${html}\n${js}`, ['type="password"', 'autocomplete="new-password"', "input.value=''", 'input[type="password"]']) && !/localStorage[^\n]*(?:nous|firecrawl|api[_-]?key)/i.test(`${html}\n${js}`));
|
||||
check('ai-provider.states', 'AI provider status states and admin messaging are represented',
|
||||
has(`${html}\n${js}`, ['/api/v1/ai/provider-config', '/api/v1/admin/ai-provider-config/test', 'Not configured', 'Invalid configuration', 'Administrator access required']));
|
||||
|
||||
const routes = [
|
||||
'/api/v1/auth/me', '/api/v1/auth/login', '/api/v1/auth/logout', '/api/v1/businesses',
|
||||
@@ -87,7 +91,7 @@ const routes = [
|
||||
'/api/v1/merge-history', '/api/v1/scoring/summary', '/api/v1/score-rules',
|
||||
'/api/v1/pipeline-entries', '/api/v1/interactions', '/api/v1/reports/pipeline',
|
||||
'/api/v1/reports/outcomes', '/api/v1/reports/activity', '/api/v1/suppressions',
|
||||
'/api/v1/ai-runs', '/api/v1/outreach/drafts', '/api/v1/outreach/provider-config'
|
||||
'/api/v1/ai-runs', '/api/v1/outreach/drafts', '/api/v1/outreach/provider-config', '/api/v1/ai/provider-config', '/api/v1/admin/ai-provider-config/test'
|
||||
];
|
||||
check('routes.contracts', 'operator API route contracts are referenced by the client',
|
||||
routes.every(route => js.includes(route)), routes.filter(route => !js.includes(route)).join(', '));
|
||||
|
||||
Reference in New Issue
Block a user