Complete RedFlag codebase with two major security audit implementations.
== A-1: Ed25519 Key Rotation Support ==
Server:
- SignCommand sets SignedAt timestamp and KeyID on every signature
- signing_keys database table (migration 020) for multi-key rotation
- InitializePrimaryKey registers active key at startup
- /api/v1/public-keys endpoint for rotation-aware agents
- SigningKeyQueries for key lifecycle management
Agent:
- Key-ID-aware verification via CheckKeyRotation
- FetchAndCacheAllActiveKeys for rotation pre-caching
- Cache metadata with TTL and staleness fallback
- SecurityLogger events for key rotation and command signing
== A-2: Replay Attack Fixes (F-1 through F-7) ==
F-5 CRITICAL - RetryCommand now signs via signAndCreateCommand
F-1 HIGH - v3 format: "{agent_id}:{cmd_id}:{type}:{hash}:{ts}"
F-7 HIGH - Migration 026: expires_at column with partial index
F-6 HIGH - GetPendingCommands/GetStuckCommands filter by expires_at
F-2 HIGH - Agent-side executedIDs dedup map with cleanup
F-4 HIGH - commandMaxAge reduced from 24h to 4h
F-3 CRITICAL - Old-format commands rejected after 48h via CreatedAt
Verification fixes: migration idempotency (ETHOS #4), log format
compliance (ETHOS #1), stale comments updated.
All 24 tests passing. Docker --no-cache build verified.
See docs/ for full audit reports and deviation log (DEV-001 to DEV-019).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
80 lines
1.9 KiB
JavaScript
80 lines
1.9 KiB
JavaScript
/** @type {import('tailwindcss').Config} */
|
|
export default {
|
|
content: [
|
|
"./index.html",
|
|
"./src/**/*.{js,ts,jsx,tsx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
primary: {
|
|
50: '#fef2f2',
|
|
100: '#fee2e2',
|
|
200: '#fecaca',
|
|
300: '#fca5a5',
|
|
400: '#f87171',
|
|
500: '#ef4444',
|
|
600: '#dc2626',
|
|
700: '#b91c1c',
|
|
800: '#991b1b',
|
|
900: '#7f1d1d',
|
|
},
|
|
success: {
|
|
50: '#f0fdf4',
|
|
100: '#dcfce7',
|
|
200: '#bbf7d0',
|
|
300: '#86efac',
|
|
400: '#4ade80',
|
|
500: '#22c55e',
|
|
600: '#16a34a',
|
|
700: '#15803d',
|
|
800: '#166534',
|
|
900: '#14532d',
|
|
},
|
|
warning: {
|
|
50: '#fffbeb',
|
|
100: '#fef3c7',
|
|
200: '#fde68a',
|
|
300: '#fcd34d',
|
|
400: '#fbbf24',
|
|
500: '#f59e0b',
|
|
600: '#d97706',
|
|
700: '#b45309',
|
|
800: '#92400e',
|
|
900: '#78350f',
|
|
},
|
|
danger: {
|
|
50: '#fef2f2',
|
|
100: '#fee2e2',
|
|
200: '#fecaca',
|
|
300: '#fca5a5',
|
|
400: '#f87171',
|
|
500: '#ef4444',
|
|
600: '#dc2626',
|
|
700: '#b91c1c',
|
|
800: '#991b1b',
|
|
900: '#7f1d1d',
|
|
}
|
|
},
|
|
fontFamily: {
|
|
mono: ['JetBrains Mono', 'Fira Code', 'Monaco', 'monospace'],
|
|
},
|
|
animation: {
|
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
'fade-in': 'fadeIn 0.5s ease-in-out',
|
|
'slide-up': 'slideUp 0.3s ease-out',
|
|
},
|
|
keyframes: {
|
|
fadeIn: {
|
|
'0%': { opacity: '0' },
|
|
'100%': { opacity: '1' },
|
|
},
|
|
slideUp: {
|
|
'0%': { transform: 'translateY(10px)', opacity: '0' },
|
|
'100%': { transform: 'translateY(0)', opacity: '1' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
} |