sync: malware page, security alerts, review diagnostics, skill detail improvements
- Add malware security advisory page and SecurityAlertBanner component - Add review diagnostics API and reviewed stats page - Improve skill detail page with better scoring display and metadata - Update review API endpoints with enhanced filtering and stats - Add skill file serving improvements and cache enhancements - Remove legacy curation scripts (moved to internal tooling) - Update CLI search with score filtering support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
import { createDb, skillReviewQueries } from '@skillhub/db';
|
||||
import { createDb, skillQueries, skillReviewQueries } from '@skillhub/db';
|
||||
import { requireAdmin } from '@/lib/admin-auth';
|
||||
import { withRateLimit, createRateLimitResponse, createRateLimitHeaders } from '@/lib/rate-limit';
|
||||
|
||||
@@ -24,6 +24,7 @@ interface ReviewItem {
|
||||
set_verified?: boolean;
|
||||
review_version?: number;
|
||||
reviewer?: string;
|
||||
recommendation?: 'flag-malicious' | null;
|
||||
}
|
||||
|
||||
function validateReviews(body: unknown): { reviews: ReviewItem[] } | { error: string } {
|
||||
@@ -74,6 +75,12 @@ function validateReviews(body: unknown): { reviews: ReviewItem[] } | { error: st
|
||||
return { error: `reviews[${i}].reviewer must be a non-empty string (max 50 chars)` };
|
||||
}
|
||||
}
|
||||
// Validate recommendation
|
||||
if (item.recommendation !== undefined && item.recommendation !== null) {
|
||||
if (item.recommendation !== 'flag-malicious') {
|
||||
return { error: `reviews[${i}].recommendation must be 'flag-malicious' or null` };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { reviews: reviews as ReviewItem[] };
|
||||
@@ -134,6 +141,7 @@ export async function POST(request: NextRequest) {
|
||||
i18nPriority: r.i18n_priority,
|
||||
contentHashAtReview: r.content_hash_at_review,
|
||||
reviewVersion: r.review_version,
|
||||
recommendation: r.recommendation ?? undefined,
|
||||
}));
|
||||
|
||||
await skillReviewQueries.createBatch(db, dbReviews);
|
||||
@@ -147,10 +155,20 @@ export async function POST(request: NextRequest) {
|
||||
await skillReviewQueries.updateSkillReviewStatus(db, r.skill_id, newStatus, r.ai_score, new Date());
|
||||
}
|
||||
|
||||
// Flag malicious skills
|
||||
let flaggedCount = 0;
|
||||
for (const r of reviews) {
|
||||
if (r.recommendation === 'flag-malicious') {
|
||||
await skillQueries.flagMalicious(db, r.skill_id);
|
||||
flaggedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
submitted: reviews.length,
|
||||
verified: verifiedCount,
|
||||
flagged: flaggedCount,
|
||||
},
|
||||
{
|
||||
headers: createRateLimitHeaders(rateLimitResult),
|
||||
|
||||
Reference in New Issue
Block a user