feat: auth service + security audit fixes + cleanup legacy services
Major changes:
- Add auth-svc: JWT auth, register/login/refresh, password reset
- Add auth UI: modals, pages (/login, /register, /forgot-password)
- Add usage tracking (usage_metrics table, daily limits)
- Add tiered rate limiting (free/pro/business)
- Add LLM usage limits per tier
Security fixes:
- All repos now require userID for Update/Delete operations
- JWT middleware in chat-svc, llm-svc, agent-svc, discover-svc
- ErrNotFound/ErrForbidden errors for proper access control
Cleanup:
- Remove legacy TypeScript services/ directory
- Remove computer-svc (to be reimplemented)
- Remove old deploy/docker configs
New files:
- backend/cmd/auth-svc/main.go
- backend/internal/auth/{types,repository}.go
- backend/internal/usage/{types,repository}.go
- backend/pkg/middleware/{llm_limits,ratelimit_tiered}.go
- backend/webui/src/components/auth/*
- backend/webui/src/app/(auth)/*
Made-with: Cursor
This commit is contained in:
@@ -414,6 +414,16 @@ body {
|
||||
background: hsl(240 4% 28%);
|
||||
}
|
||||
|
||||
/* Hide scrollbar utility */
|
||||
.scrollbar-hide {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: hsl(239 84% 67% / 0.3);
|
||||
}
|
||||
@@ -678,3 +688,172 @@ body {
|
||||
.animate-glow-pulse {
|
||||
animation: glow-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* =====================
|
||||
Computer UI Styles
|
||||
===================== */
|
||||
|
||||
/* Action step container */
|
||||
.action-step {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.action-step::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 1.25rem;
|
||||
top: 2.75rem;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
hsl(var(--border)) 0%,
|
||||
transparent 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Strikethrough animation for completed tasks */
|
||||
@keyframes strikethrough {
|
||||
from {
|
||||
width: 0;
|
||||
}
|
||||
to {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.task-completed {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.task-completed::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
height: 1px;
|
||||
background: hsl(var(--text-muted));
|
||||
animation: strikethrough 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Typing indicator */
|
||||
@keyframes typing-dot {
|
||||
0%, 20% { opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
.typing-indicator span {
|
||||
animation: typing-dot 1.4s infinite;
|
||||
}
|
||||
|
||||
.typing-indicator span:nth-child(2) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.typing-indicator span:nth-child(3) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
/* Code highlight colors */
|
||||
.code-keyword { color: #c792ea; }
|
||||
.code-string { color: #c3e88d; }
|
||||
.code-comment { color: #546e7a; font-style: italic; }
|
||||
.code-function { color: #82aaff; }
|
||||
.code-number { color: #f78c6c; }
|
||||
.code-operator { color: #89ddff; }
|
||||
|
||||
/* Thinking block pulse */
|
||||
@keyframes thinking-pulse {
|
||||
0%, 100% {
|
||||
background: hsl(239 84% 67% / 0.05);
|
||||
}
|
||||
50% {
|
||||
background: hsl(239 84% 67% / 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
.thinking-active {
|
||||
animation: thinking-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Status indicator pulse */
|
||||
@keyframes status-pulse {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.status-active {
|
||||
animation: status-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* File card hover effect */
|
||||
.file-card-hover {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.file-card-hover:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px -5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Collapsible animation */
|
||||
.collapsible-content {
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease-out, opacity 0.2s ease-out;
|
||||
}
|
||||
|
||||
/* Progress bar shimmer */
|
||||
@keyframes progress-shimmer {
|
||||
0% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-shimmer {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
hsl(239 84% 67%) 0%,
|
||||
hsl(260 90% 75%) 25%,
|
||||
hsl(187 85% 65%) 50%,
|
||||
hsl(260 90% 75%) 75%,
|
||||
hsl(239 84% 67%) 100%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: progress-shimmer 2s linear infinite;
|
||||
}
|
||||
|
||||
/* Event timeline line */
|
||||
.timeline-line {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-line::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0.5rem;
|
||||
top: 1.5rem;
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
hsl(var(--border)) 0%,
|
||||
transparent 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Artifact card glow on hover */
|
||||
.artifact-glow:hover {
|
||||
box-shadow:
|
||||
0 0 20px hsl(142 71% 45% / 0.15),
|
||||
0 4px 12px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user