secubox-openwrt/package/secubox/luci-app-secubox-admin/htdocs/luci-static/resources/secubox-admin/state-management.css
CyberMind-FR e258d86eea feat: Admin Control Center with State Management (v0.9.0)
Major feature release implementing comprehensive state management, component registry,
and admin control center with full UI integration.

## Backend Features (secubox-core v0.9.0-1)

State Management System:
-  State database (state-db.json) with 15 states across 4 categories
-  State machine with transition matrix validation
-  secubox-state CLI (8 commands: get, set, history, list, validate, sync, freeze, clear-error)
-  state-machine.sh with atomic transitions using flock
-  State history tracking with timestamps and reasons
-  Error state handling with detailed error info
-  Frozen state support for system-critical components

Component Registry System:
-  Component registry database (component-registry.json)
-  secubox-component CLI (7 commands: list, get, register, unregister, tree, affected, set-setting)
-  Component types: app, module, widget, service, composite
-  Dependency tracking (required/optional)
-  Recursive dependency tree resolution
-  Reverse dependency tracking
-  Component settings management
-  Profile tagging and filtering

Auto-Sync System:
-  secubox-sync-registry CLI for catalog synchronization
-  Auto-populate from catalog.json
-  Plugin catalog directory scanning
-  Installed package detection
-  Automatic state initialization

RPC Backend (luci.secubox):
-  6 state management RPC methods
-  5 component registry RPC methods
-  Bulk operations support
-  State validation endpoints

## Frontend Features (luci-app-secubox-admin v1.0.0-16)

UI Components:
-  state-utils.js: 20+ utility functions, state config, transition validation
-  StateIndicator.js: 5 rendering modes (badge, compact, pill, dot, statistics)
-  StateTimeline.js: 4 visualization modes (vertical, horizontal, compact, transition diagram)
-  state-management.css: 600+ lines with animations, responsive design, accessibility

Admin Control Center Dashboard:
-  System overview panel with health metrics
-  Component state summary with statistics
-  Recent state transitions timeline
-  Alerts panel for warnings and errors
-  Quick actions panel
-  Real-time updates (5-second polling)
-  Metric cards with hover effects
-  State distribution by category

API Integration (api.js):
-  11 RPC method declarations
-  Enhanced methods: getComponentWithState(), getAllComponentsWithStates()
-  Bulk operations: bulkSetComponentState()
-  State statistics: getStateStatistics()
-  Retry logic with exponential backoff
-  Promise-based async operations

## Documentation

Comprehensive Documentation:
-  API-REFERENCE.md (1,200+ lines): Complete API docs for RPC, CLI, JS
-  EXAMPLES.md (800+ lines): 30+ usage examples, shell scripts, integration patterns
-  State definitions table (15 states)
-  State transition matrix
-  Component metadata schemas
-  Error codes reference
-  Testing examples

## State Definitions

15 States Across 4 Categories:
- Persistent: available, installed, active, disabled, frozen
- Transient: installing, configuring, activating, starting, stopping, uninstalling
- Runtime: running, stopped
- Error: error (with subtypes)

State Transition Flow:
available → installing → installed → configuring → configured →
activating → active → starting → running → stopping → stopped

## Technical Details

Files Created (10 backend + 8 frontend):
Backend:
- /usr/sbin/secubox-state (12KB, 8 commands)
- /usr/sbin/secubox-component (12KB, 7 commands)
- /usr/sbin/secubox-sync-registry (8.4KB)
- /usr/share/secubox/state-machine.sh (5.2KB)
- /var/lib/secubox/state-db.json (schema)
- /var/lib/secubox/component-registry.json (schema)

Frontend:
- resources/secubox-admin/state-utils.js (~400 lines)
- resources/secubox-admin/components/StateIndicator.js (~350 lines)
- resources/secubox-admin/components/StateTimeline.js (~450 lines)
- resources/secubox-admin/state-management.css (~600 lines)
- resources/view/secubox-admin/control-center.js (~550 lines)
- resources/secubox-admin/api.js (+145 lines)

Documentation:
- docs/admin-control-center/API-REFERENCE.md (1,200+ lines)
- docs/admin-control-center/EXAMPLES.md (800+ lines)

Files Modified (3):
- package/secubox/secubox-core/Makefile (v0.8.0 → v0.9.0-1)
- package/secubox/luci-app-secubox-admin/Makefile (release 15 → 16)
- package/secubox/secubox-core/root/usr/libexec/rpcd/luci.secubox (+157 lines)

## Installation & Migration

Makefile Updates:
- Added 3 new CLI tools to install section
- Added state-machine.sh to scripts
- Updated package description
- Enhanced postinst to initialize databases
- Auto-sync registry on first install

Postinst Features:
- Automatic state-db.json initialization
- Automatic component-registry.json initialization
- Catalog sync on install
- Version announcement with new features

## Performance & Security

Performance:
- File locking (flock) for atomic state transitions
- State history limited to 100 entries per component
- RPC retry logic with exponential backoff
- Bulk operations use Promise.all for parallel execution
- Component list caching (30 seconds)

Security:
- Frozen state prevents unauthorized modifications
- All state changes logged with timestamp and reason
- System-critical components have additional safeguards
- Proper authentication required for state transitions

## Testing & Validation

Features:
- State transition validation
- Component dependency resolution
- Circular dependency detection
- State consistency checker
- Integration test scripts included in docs

## Breaking Changes

None - Backward Compatible:
- Existing RPC methods remain functional
- State-aware methods are additive
- Components without state default to 'available'
- Migration is automatic on install

## Statistics

Total Implementation:
- Lines of Code: ~4,000
  - Backend: ~1,800 (Bash + JSON)
  - Frontend: ~2,200 (JavaScript + CSS)
  - Documentation: ~2,000 (Markdown)
- Functions/Commands: 40+
- RPC Methods: 11
- CLI Commands: 22
- UI Components: 5
- Documentation Pages: 2

## Next Phase

Remaining from Plan:
- Phase 4: System Hub integration
- Phase 5: Migration script (secubox-migrate-state)
- Phase 6: Additional documentation (ARCHITECTURE.md, STATE-MANAGEMENT.md, etc.)
- Phase 7: Additional UI views (components.js, state-manager.js, debug-panel.js)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-05 10:05:32 +01:00

602 lines
9.7 KiB
CSS

/**
* SecuBox State Management Styles
* Comprehensive CSS for state indicators, timelines, and visualizations
*/
/* ===== State Badge Components ===== */
.cyber-badge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.5rem;
border-radius: 0.375rem;
font-size: 0.75rem;
font-weight: 600;
transition: all 0.2s ease;
}
.state-badge {
border-width: 1px;
border-style: solid;
}
/* State-specific badge colors */
.state-available {
color: #6b7280;
background-color: rgba(107, 114, 128, 0.1);
border-color: rgba(107, 114, 128, 0.25);
}
.state-installing {
color: #3b82f6;
background-color: rgba(59, 130, 246, 0.1);
border-color: rgba(59, 130, 246, 0.25);
}
.state-installed {
color: #8b5cf6;
background-color: rgba(139, 92, 246, 0.1);
border-color: rgba(139, 92, 246, 0.25);
}
.state-configuring {
color: #3b82f6;
background-color: rgba(59, 130, 246, 0.1);
border-color: rgba(59, 130, 246, 0.25);
}
.state-configured {
color: #8b5cf6;
background-color: rgba(139, 92, 246, 0.1);
border-color: rgba(139, 92, 246, 0.25);
}
.state-activating {
color: #3b82f6;
background-color: rgba(59, 130, 246, 0.1);
border-color: rgba(59, 130, 246, 0.25);
}
.state-active {
color: #06b6d4;
background-color: rgba(6, 182, 212, 0.1);
border-color: rgba(6, 182, 212, 0.25);
}
.state-starting {
color: #3b82f6;
background-color: rgba(59, 130, 246, 0.1);
border-color: rgba(59, 130, 246, 0.25);
}
.state-running {
color: #10b981;
background-color: rgba(16, 185, 129, 0.1);
border-color: rgba(16, 185, 129, 0.25);
}
.state-stopping {
color: #f59e0b;
background-color: rgba(245, 158, 11, 0.1);
border-color: rgba(245, 158, 11, 0.25);
}
.state-stopped {
color: #6b7280;
background-color: rgba(107, 114, 128, 0.1);
border-color: rgba(107, 114, 128, 0.25);
}
.state-error {
color: #ef4444;
background-color: rgba(239, 68, 68, 0.1);
border-color: rgba(239, 68, 68, 0.25);
}
.state-frozen {
color: #06b6d4;
background-color: rgba(6, 182, 212, 0.1);
border-color: rgba(6, 182, 212, 0.25);
}
.state-disabled {
color: #9ca3af;
background-color: rgba(156, 163, 175, 0.1);
border-color: rgba(156, 163, 175, 0.25);
}
.state-uninstalling {
color: #f59e0b;
background-color: rgba(245, 158, 11, 0.1);
border-color: rgba(245, 158, 11, 0.25);
}
.state-unknown {
color: #6b7280;
background-color: rgba(107, 114, 128, 0.1);
border-color: rgba(107, 114, 128, 0.25);
}
/* Category-based styling */
.state-category-persistent {
border-style: solid;
}
.state-category-transient {
border-style: dashed;
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.state-category-runtime {
border-style: solid;
box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.1);
}
.state-category-error {
border-style: solid;
box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.1);
}
/* ===== State Pill Components ===== */
.state-pill {
display: inline-flex;
align-items: center;
padding: 0.5rem 0.75rem;
border-radius: 9999px;
border-width: 2px;
border-style: solid;
transition: all 0.2s ease;
}
.state-pill:hover {
transform: translateY(-1px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.state-pill-icon {
font-size: 1.25rem;
margin-right: 0.5rem;
}
.state-pill-label {
font-weight: 600;
font-size: 0.875rem;
}
.state-pill-description,
.state-pill-time {
font-size: 0.75rem;
margin-top: 0.125rem;
}
/* ===== State Indicator Compact ===== */
.state-indicator-compact {
display: inline-block;
width: 1.5rem;
height: 1.5rem;
line-height: 1.5rem;
text-align: center;
border-radius: 50%;
font-size: 0.875rem;
transition: all 0.2s ease;
}
.state-indicator-compact:hover {
transform: scale(1.1);
}
/* ===== State Dot ===== */
.state-dot {
display: inline-block;
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
transition: all 0.2s ease;
}
.state-dot:hover {
transform: scale(1.2);
}
/* ===== State Timeline ===== */
.state-timeline {
position: relative;
padding-left: 2rem;
}
.timeline-line {
position: absolute;
left: 0.5rem;
top: 0;
bottom: 0;
width: 2px;
background-color: #e5e7eb;
}
.timeline-entry {
position: relative;
margin-bottom: 1.5rem;
animation: fadeInUp 0.3s ease;
}
.timeline-entry-error .timeline-content {
border-left-width: 4px;
}
.timeline-entry-transient .timeline-dot {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.timeline-dot {
position: absolute;
left: -1.75rem;
top: 0.25rem;
width: 1rem;
height: 1rem;
border-radius: 50%;
border: 3px solid #ffffff;
z-index: 10;
transition: all 0.2s ease;
}
.timeline-entry:hover .timeline-dot {
transform: scale(1.2);
}
.timeline-content {
padding: 0.75rem;
border-radius: 0.5rem;
border-left-width: 3px;
border-left-style: solid;
transition: all 0.2s ease;
}
.timeline-content:hover {
transform: translateX(4px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.timeline-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.5rem;
}
.timeline-timestamp {
font-size: 0.75rem;
color: #6b7280;
}
.timeline-reason {
font-size: 0.875rem;
color: #4b5563;
margin-bottom: 0.25rem;
}
.timeline-error-details {
margin-top: 0.5rem;
padding: 0.5rem;
background-color: #fee2e2;
border-radius: 0.375rem;
border-left: 3px solid #ef4444;
}
.timeline-metadata {
margin-top: 0.5rem;
padding-top: 0.5rem;
border-top: 1px solid rgba(0, 0, 0, 0.1);
font-size: 0.75rem;
color: #6b7280;
}
/* ===== Timeline Compact ===== */
.state-timeline-compact {
display: flex;
align-items: center;
gap: 0.25rem;
}
.state-timeline-empty {
padding: 2rem;
text-align: center;
color: #6b7280;
}
/* ===== Timeline Horizontal ===== */
.state-timeline-horizontal {
display: flex;
align-items: center;
gap: 0.5rem;
overflow-x: auto;
padding: 1rem 0;
}
.timeline-node {
display: flex;
flex-direction: column;
align-items: center;
min-width: 80px;
transition: all 0.2s ease;
}
.timeline-node:hover {
transform: translateY(-4px);
}
.timeline-arrow {
font-size: 1.25rem;
color: #9ca3af;
margin: 0 0.5rem;
}
/* ===== State Progress ===== */
.state-progress {
display: flex;
align-items: center;
gap: 0.5rem;
}
.state-progress-step {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
transition: all 0.3s ease;
}
.state-progress-step.active {
transform: scale(1.05);
}
.state-progress-icon {
width: 2rem;
height: 2rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid;
font-weight: 600;
transition: all 0.3s ease;
}
.state-progress-step:hover .state-progress-icon {
transform: scale(1.1);
}
.state-progress-label {
margin-top: 0.25rem;
font-size: 0.75rem;
}
.state-progress-connector {
flex: 1;
height: 2px;
margin-bottom: 1.5rem;
transition: all 0.3s ease;
}
/* ===== State Statistics ===== */
.state-statistics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
}
.state-stat-card {
padding: 1rem;
border-radius: 0.5rem;
border-left: 4px solid;
transition: all 0.2s ease;
}
.state-stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.state-stat-count {
font-size: 1.5rem;
font-weight: 700;
}
.state-stat-label {
font-size: 0.875rem;
color: #6b7280;
margin-top: 0.25rem;
}
/* ===== State Transition Diagram ===== */
.state-transition-diagram {
padding: 1rem;
}
.transition-card {
padding: 0.75rem;
border-radius: 0.5rem;
border: 2px solid;
cursor: pointer;
transition: all 0.2s ease;
}
.transition-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
/* ===== Animations ===== */
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* ===== Utility Classes ===== */
.state-loading {
animation: spin 1s linear infinite;
}
.state-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.state-fade-in {
animation: fadeInUp 0.3s ease;
}
/* ===== Responsive Design ===== */
@media (max-width: 768px) {
.state-timeline {
padding-left: 1.5rem;
}
.timeline-dot {
left: -1.5rem;
width: 0.875rem;
height: 0.875rem;
}
.timeline-line {
left: 0.375rem;
}
.state-statistics {
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
.state-timeline-horizontal {
overflow-x: scroll;
}
.timeline-node {
min-width: 60px;
}
.state-pill {
font-size: 0.75rem;
padding: 0.375rem 0.625rem;
}
}
/* ===== Dark Mode Support (optional) ===== */
@media (prefers-color-scheme: dark) {
.timeline-line {
background-color: #374151;
}
.timeline-timestamp,
.timeline-metadata,
.state-stat-label {
color: #9ca3af;
}
.timeline-reason {
color: #d1d5db;
}
.timeline-dot {
border-color: #1f2937;
}
.state-timeline-empty {
color: #9ca3af;
}
}
/* ===== Print Styles ===== */
@media print {
.state-badge,
.state-pill,
.timeline-entry {
page-break-inside: avoid;
}
.timeline-entry:hover .timeline-dot,
.state-dot:hover,
.state-indicator-compact:hover {
transform: none;
}
.transition-card:hover {
transform: none;
box-shadow: none;
}
}
/* ===== Accessibility Enhancements ===== */
.state-badge:focus,
.state-pill:focus,
.transition-card:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
/* High contrast mode */
@media (prefers-contrast: high) {
.state-badge,
.state-pill {
border-width: 2px;
}
.timeline-content {
border-left-width: 4px;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.state-category-transient,
.timeline-entry-transient .timeline-dot,
.state-pulse {
animation: none;
}
.timeline-entry,
.state-fade-in {
animation: none;
}
* {
transition: none !important;
}
}