coding-agent-search 0.5.1

Unified TUI search over local coding agent histories
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Encrypted cass Archive</title>

    <!-- CSP: No unsafe-inline, no eval -->
    <meta http-equiv="Content-Security-Policy" content="
        default-src 'self';
        script-src 'self' 'wasm-unsafe-eval';
        style-src 'self';
        img-src 'self' data: blob:;
        connect-src 'self';
        worker-src 'self' blob:;
        object-src 'none';
        frame-ancestors 'none';
        form-action 'none';
        base-uri 'none';
    ">
    <meta name="referrer" content="no-referrer">
    <meta name="robots" content="noindex,nofollow">

    <link rel="stylesheet" href="styles.css">
    <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🔐</text></svg>">
</head>
<body>
    <!-- Skip link for keyboard users -->
    <a href="#main-content" class="skip-link">Skip to main content</a>

    <!-- Screen reader announcer for dynamic content -->
    <div id="sr-announcer" class="visually-hidden" aria-live="polite" aria-atomic="true"></div>
    <div id="sr-alert" class="visually-hidden" role="alert" aria-live="assertive"></div>

    <!-- COI status screen (shown during setup/reload check) -->
    <div id="coi-status" class="coi-container hidden" role="status" aria-live="polite"></div>

    <!-- Auth screen (shown after COI check passes) -->
    <div id="auth-screen" class="auth-container" role="region" aria-label="Authentication">
        <div class="auth-card">
            <div class="auth-header">
                <div class="logo">🔐</div>
                <h1>cass Archive</h1>
                <p class="subtitle">This archive is encrypted for your privacy.</p>
            </div>

            <!-- Integrity fingerprint (verify before entering password) -->
            <div id="fingerprint-display" class="fingerprint">
                <span class="fingerprint-label">Fingerprint:</span>
                <code id="fingerprint-value">loading...</code>
                <button id="fingerprint-help" type="button" class="help-btn" aria-label="What is this?">?</button>
            </div>

            <div id="fingerprint-tooltip" class="tooltip hidden">
                Verify this fingerprint matches the one shown when the archive was created.
                This ensures the archive hasn't been tampered with.
            </div>

            <form class="auth-form" id="auth-form" role="form" aria-label="Unlock archive">
                <div class="form-group">
                    <label for="password" id="password-label">Password</label>
                    <div class="password-input-wrapper">
                        <input type="password" id="password" autocomplete="current-password"
                               placeholder="Enter your archive password"
                               aria-labelledby="password-label"
                               aria-describedby="password-hint"
                               required>
                        <button id="toggle-password" type="button" class="toggle-password"
                                aria-label="Show password" aria-pressed="false">
                            <span class="eye-icon" aria-hidden="true">👁</span>
                        </button>
                    </div>
                    <span id="password-hint" class="visually-hidden">
                        Enter the password that was set when this archive was created
                    </span>
                    <div id="strength-meter" class="strength-meter" aria-hidden="true">
                        <div class="strength-bar"></div>
                    </div>
                    <div class="strength-info">
                        <span id="strength-label" class="strength-label"></span>
                    </div>
                    <ul id="strength-suggestions" class="strength-suggestions" aria-live="polite"></ul>
                </div>

                <button id="unlock-btn" type="submit" class="btn btn-primary">
                    <span class="btn-text">Unlock Archive</span>
                    <span class="btn-icon" aria-hidden="true">🔓</span>
                </button>

                <div class="divider" role="separator">
                    <span>or</span>
                </div>

                <button id="qr-btn" type="button" class="btn btn-secondary">
                    <span class="btn-icon" aria-hidden="true">📷</span>
                    <span class="btn-text">Scan Recovery QR Code</span>
                </button>
            </form>

            <div id="qr-scanner" class="qr-scanner hidden">
                <div class="qr-scanner-header">
                    <h2>Scan Recovery QR Code</h2>
                    <button id="qr-cancel-btn" type="button" class="btn-close" aria-label="Close scanner"></button>
                </div>
                <div id="qr-reader"></div>
                <p class="qr-instructions">Position the QR code within the frame</p>
            </div>

            <div id="auth-error" class="error hidden" role="alert" aria-live="assertive">
                <span class="error-icon" aria-hidden="true">⚠️</span>
                <span class="error-message"></span>
            </div>

            <div id="auth-progress" class="progress hidden" role="status" aria-live="polite">
                <div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
                    <div class="progress-fill"></div>
                </div>
                <span class="progress-text">Deriving key...</span>
            </div>
        </div>

        <footer class="auth-footer">
            <p>Generated by <a href="https://github.com/Dicklesworthstone/coding_agent_session_search" target="_blank" rel="noopener">cass</a></p>
        </footer>
    </div>

    <!-- App screen (shown after unlock) -->
    <div id="app-screen" class="app-container hidden">
        <!-- Header -->
        <header class="app-header" role="banner">
            <div class="header-left">
                <span class="logo-small" aria-hidden="true">🔐</span>
                <h1>cass Archive</h1>
            </div>
            <nav class="header-right" role="navigation" aria-label="Main navigation">
                <button id="lock-btn" type="button" class="btn btn-small">
                    <span class="btn-icon" aria-hidden="true">🔒</span>
                    <span class="btn-text">Lock</span>
                </button>
            </nav>
        </header>

        <!-- Main content area (populated by viewer.js) -->
        <main id="main-content" role="main" aria-label="Archive content">
            <div class="loading-state" role="status" aria-live="polite">
                <div class="spinner" aria-hidden="true"></div>
                <p>Loading database...</p>
            </div>
        </main>
    </div>

    <!-- Main authentication module -->
    <script type="module" src="auth.js"></script>
</body>
</html>