Skip to content

Read/Write Mode Toggle (UI) #242

Description

@Entropy-rgb

Problem Statement

Write mode is only available via CLI flag (--allow-writes in main.py). No UI toggle for runtime switching. Users must restart the server to enable/disable write mode, which is impractical for production environments.

Proposed Solution

Add a UI toggle in Settings to enable/disable write mode at runtime, with safety confirmations and audit logging.

Acceptance Criteria

  • Settings toggle for read/write mode (admin only)
  • Confirmation dialog when enabling write mode
  • Visual indicator when write mode is active
  • Audit logging for all write operations
  • Automatic disable after session timeout
  • Per-database write permissions
  • SQL whitelist/blacklist for write operations
  • Rollback capability for write operations

Technical Approach

Backend Changes

1. Runtime toggle (backend/app/config.py):

# Add to config
WRITE_MODE_CONFIG = {
    "allow_writes": False,  # Default off
    "write_timeout": 3600,  # Auto-disable after 1 hour
    "allowed_tables": [],  # Empty = all tables allowed
    "blocked_tables": [],  # Tables that can never be written to
}

2. Write mode endpoint (backend/app/routes/system.py):

@router.post("/api/config/write-mode")
async def toggle_write_mode(
    req: WriteModeRequest,
    user = Depends(require_role(Role.admin)),
    cfg = Depends(get_cfg)
):
    """Toggle write mode at runtime."""
    cfg["allow_writes"] = req.allow_writes
    cfg["write_mode_enabled_at"] = datetime.utcnow().isoformat()
    save_config(cfg)
    
    # Log the change
    audit_logger.log_write_mode_toggle(user.id, req.allow_writes)
    
    return {"allow_writes": req.allow_writes}

3. Write operation logging (backend/app/services/audit.py):

async def log_write_operation(self, user_id: str, sql: str, result: dict):
    """Log all write operations for audit."""
    entry = AuditLog(
        user_id=user_id,
        action="write_operation",
        resource_type="database",
        details={
            "sql": sql,
            "rows_affected": result.get("rows_affected"),
            "success": result.get("success")
        }
    )
    self.db.add(entry)
    await self.db.commit()

Frontend Changes

1. Write mode toggle (frontend/src/lib/components/Settings.svelte):

<script>
    export let config;
    
    let writeMode = config.allow_writes || false;
    let showConfirmation = false;
    
    async function toggleWriteMode() {
        if (writeMode) {
            // Enabling - show confirmation
            showConfirmation = true;
        } else {
            // Disabling - no confirmation needed
            await updateWriteMode(false);
        }
    }
    
    async function confirmEnable() {
        await updateWriteMode(true);
        showConfirmation = false;
    }
    
    async function updateWriteMode(enabled) {
        await apiCall('/api/config/write-mode', {
            method: 'POST',
            body: JSON.stringify({ allow_writes: enabled })
        });
        writeMode = enabled;
    }
</script>

<div class="settings-section">
    <h3>Write Mode</h3>
    <p>Allow SQL queries that modify data (INSERT, UPDATE, DELETE)</p>
    
    <label class="toggle">
        <input type="checkbox" bind:checked={writeMode} on:change={toggleWriteMode} />
        <span class="slider"></span>
        <span class="label">{writeMode ? 'Enabled' : 'Disabled'}</span>
    </label>
    
    {#if writeMode}
        <div class="warning">
            ⚠️ Write mode is active. All write operations are logged.
        </div>
    {/if}
</div>

{#if showConfirmation}
    <div class="modal">
        <h3>Enable Write Mode?</h3>
        <p>This will allow SQL queries that modify data. All write operations will be logged for audit purposes.</p>
        <div class="actions">
            <button on:click={confirmEnable}>Yes, Enable</button>
            <button on:click={() => showConfirmation = false}>Cancel</button>
        </div>
    </div>
{/if}

2. Visual indicator - Show write mode status in header/sidebar

3. Per-database settings - Allow different write modes per database connection

Key Files

  • backend/app/config.py - Write mode config
  • backend/app/routes/system.py - Write mode endpoint
  • backend/app/services/audit.py - Write logging
  • frontend/src/lib/components/Settings.svelte - Toggle UI

Related Issues

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions