feat(HAI-001): add API rate limiting and replace emojis with Lucide icons

- Add rate limiting middleware to dashboard API endpoints
- Install lucide-react and replace emoji usage with Lucide icons across dashboard components
- Add rate limiter unit tests
- Document API rate limiting in README
- Refactor engine executor/triage and remove unused reviewer module
This commit is contained in:
Dustin Byrne
2026-03-25 20:33:37 -04:00
12 changed files with 497 additions and 9 deletions

View File

@@ -1,3 +1,5 @@
import { Settings } from "lucide-react";
interface HeaderProps {
onOpenSettings?: () => void;
}
@@ -11,7 +13,7 @@ export function Header({ onOpenSettings }: HeaderProps) {
</div>
<div className="header-actions">
<button className="btn-icon" onClick={onOpenSettings} title="Settings">
<Settings size={16} />
</button>
</div>
</header>

View File

@@ -1,4 +1,5 @@
import { useState, useCallback, useEffect, useRef } from "react";
import { Link } from "lucide-react";
import type { Task, TaskCreateInput } from "@hai/core";
import type { ToastType } from "../hooks/useToast";
@@ -77,7 +78,7 @@ export function InlineCreateCard({ tasks, onSubmit, onCancel, addToast }: Inline
className="btn btn-sm dep-trigger"
onClick={() => setShowDeps((v) => !v)}
>
{dependencies.length > 0 ? ` ${dependencies.length} deps` : " Deps"}
<Link size={12} style={{ verticalAlign: 'middle' }} />{dependencies.length > 0 ? ` ${dependencies.length} deps` : " Deps"}
</button>
{showDeps && (
<div className="dep-dropdown">

View File

@@ -1,4 +1,5 @@
import { useCallback, useState } from "react";
import { Link, Clock } from "lucide-react";
import type { Task, TaskDetail, Column } from "@hai/core";
import { fetchTaskDetail } from "../api";
import type { ToastType } from "../hooks/useToast";
@@ -80,10 +81,10 @@ export function TaskCard({ task, queued, onOpenDetail, addToast }: TaskCardProps
<div className="card-meta">
{task.dependencies && task.dependencies.length > 0 && (
<span className="card-dep-badge">
{task.dependencies.length} dep{task.dependencies.length > 1 ? "s" : ""}
<Link size={12} style={{ verticalAlign: 'middle' }} /> {task.dependencies.length} dep{task.dependencies.length > 1 ? "s" : ""}
</span>
)}
{queued && <span className="queued-badge"> Queued</span>}
{queued && <span className="queued-badge"><Clock size={12} style={{ verticalAlign: 'middle' }} /> Queued</span>}
</div>
)}
</div>

View File

@@ -1,4 +1,5 @@
import type { Task, TaskDetail } from "@hai/core";
import { ClipboardList, GitBranch } from "lucide-react";
import { TaskCard } from "./TaskCard";
import type { ToastType } from "../hooks/useToast";
@@ -21,7 +22,7 @@ export function WorktreeGroup({
<div className="worktree-group">
<div className="worktree-group-header">
<span className="worktree-icon">
{label === "Up Next" || label === "Unassigned" ? "📋" : "🌿"}
{label === "Up Next" || label === "Unassigned" ? <ClipboardList size={14} /> : <GitBranch size={14} />}
</span>
<span className="worktree-label">{label}</span>
</div>