Skip to content

Commit e262e69

Browse files
DMontgomery40Faxbot Agentclaude
authored
PR16: ConfigurationManager with Hierarchical Config Support (#17)
* fix(admin-ui): fix TypeScript build errors in ConfigurationManager component - Remove unused React import - Remove unused Accordion-related imports - Remove unused ExpandMoreIcon import - Remove unused safeKeys variable (use setter only) - Remove unused useTraits import and usage - Fix hasConfigAccess to not use non-existent traits.has method This completes the admin UI build fixes for the feat/pr16-config-manager branch. * PR16: Add initial ConfigurationManager component (read-only) - Created ConfigurationManager.tsx with hierarchical config display - Added v4 config API endpoints (effective, hierarchy, safe-keys, flush-cache) - Implemented basic HierarchicalConfigProvider with env/default fallback - Added CacheManager with in-memory storage - Wired ConfigurationManager into Admin Console Settings tab - UI displays config sources, hierarchy levels, and masked secrets Note: This is the minimal read-only implementation per Phase 3 runbook. Full database-backed hierarchy and editing capabilities will be added in subsequent PRs (PR17-21). * PR16: Implement comprehensive ConfigurationManager with database support Major enhancements to hierarchical configuration system: Backend Improvements: - Added database models for hierarchical config (global, tenant, department, group, user levels) - Implemented ConfigEncryption class with Fernet encryption for sensitive values - Enhanced HierarchicalConfigProvider with full database-backed resolution - Added Redis caching with automatic memory fallback - Created migration script for config tables - Added validation framework for safe configuration keys - Implemented masked value handling for audit trail Frontend Enhancements: - Enhanced ConfigurationManager UI with category-based organization - Added search and filter functionality for configuration keys - Improved hierarchy visualization with source badges - Added cache statistics display - Implemented proper masking for sensitive values - Added comprehensive key coverage (30+ config keys across 8 categories) Infrastructure: - Added required dependencies (cryptography, redis, sse-starlette) - Updated anyio to 4.11.0 to resolve dependency conflicts - Prepared foundation for SSE diagnostics and circuit breakers This establishes the full framework for Phase 3 configuration management. PR17 will add write capabilities for safe keys, followed by SSE diagnostics, circuit breakers, and rate limiting in subsequent PRs. --------- Co-authored-by: Faxbot Agent <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent a338caa commit e262e69

File tree

9 files changed

+789
-5
lines changed

9 files changed

+789
-5
lines changed

api/admin_ui/src/App.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import ListAltIcon from '@mui/icons-material/ListAlt';
3333
import InboxIcon from '@mui/icons-material/Inbox';
3434
import VpnKeyIcon from '@mui/icons-material/VpnKey';
3535
import CodeIcon from '@mui/icons-material/Code';
36+
import TuneIcon from '@mui/icons-material/Tune';
3637
import TerminalIcon from '@mui/icons-material/Terminal';
3738
import AssessmentIcon from '@mui/icons-material/Assessment';
3839
import DescriptionIcon from '@mui/icons-material/Description';
@@ -60,6 +61,7 @@ import TunnelSettings from './components/TunnelSettings';
6061
import ProviderSetupWizard from './components/ProviderSetupWizard';
6162
import InboundWebhookTester from './components/InboundWebhookTester';
6263
import OutboundSmokeTests from './components/OutboundSmokeTests';
64+
import ConfigurationManager from './components/ConfigurationManager';
6365
import { ThemeProvider } from './theme/ThemeContext';
6466
import { ThemeToggle } from './components/ThemeToggle';
6567

@@ -293,6 +295,7 @@ function AppContent() {
293295
const settingsItems = [
294296
{ label: 'Setup', icon: <HelpIcon /> },
295297
{ label: 'Settings', icon: <SettingsIcon /> },
298+
{ label: 'Configuration', icon: <TuneIcon /> },
296299
{ label: 'Keys', icon: <VpnKeyIcon /> },
297300
{ label: 'MCP', icon: <CodeIcon /> },
298301
];
@@ -776,8 +779,9 @@ function AppContent() {
776779
<Settings client={client!} readOnly={!hasTrait('role.admin')} />
777780
</Box>
778781
)}
779-
{settingsTab === 2 && <ApiKeys client={client!} readOnly={!hasTrait('role.admin')} />}
780-
{settingsTab === 3 && <MCP client={client!} />}
782+
{settingsTab === 2 && <ConfigurationManager client={client!} docsBase={uiConfig?.docs_base || adminConfig?.branding?.docs_base} />}
783+
{settingsTab === 3 && <ApiKeys client={client!} readOnly={!hasTrait('role.admin')} />}
784+
{settingsTab === 4 && <MCP client={client!} />}
781785
</Box>
782786
</Paper>
783787
</TabPanel>

api/admin_ui/src/api/client.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,35 @@ export class AdminAPIClient {
160160
return res.json();
161161
}
162162

163+
// v4 Config (read-only baseline)
164+
async v4GetEffective(payload: { keys?: string[]; user_id?: string; tenant_id?: string; department?: string; groups?: string[] } = {}): Promise<{ schema_version: number; items: Record<string, any> }>{
165+
const res = await this.fetch('/admin/config/v4/effective', {
166+
method: 'POST',
167+
body: JSON.stringify(payload || {}),
168+
});
169+
return res.json();
170+
}
171+
172+
async v4GetHierarchy(payload: { key: string; user_id?: string; tenant_id?: string; department?: string; groups?: string[] }): Promise<any>{
173+
const res = await this.fetch('/admin/config/v4/hierarchy', {
174+
method: 'POST',
175+
body: JSON.stringify(payload || {}),
176+
});
177+
return res.json();
178+
}
179+
180+
async v4GetSafeKeys(): Promise<Record<string, any>>{
181+
const res = await this.fetch('/admin/config/v4/safe-keys');
182+
return res.json();
183+
}
184+
185+
async v4FlushCache(scope: string = '*'): Promise<{ ok: boolean; deleted?: number | null; scope: string; backend?: string }>{
186+
const res = await this.fetch(`/admin/config/v4/flush-cache?scope=${encodeURIComponent(scope)}`, {
187+
method: 'POST',
188+
});
189+
return res.json();
190+
}
191+
163192
// User traits (admin-only)
164193
async getUserTraits(): Promise<{ schema_version: number; user: { id: string }; traits: string[] }>{
165194
const res = await this.fetch('/admin/user/traits');

0 commit comments

Comments
 (0)