mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-05-11 06:11:15 +00:00
feat: grouping phase 1 — schema, ungrouped tab, time-window grouping, hash verification
Schema: - Add GroupingSource enum (ALBUM, MANUAL, AUTO_TIME, AUTO_PATTERN, etc.) - Add groupingSource field to PackageGroup with backfill - Add SystemNotification model for persistent alerts - Add NotificationType and NotificationSeverity enums Ungrouped staging tab: - Add listUngroupedPackages/countUngroupedPackages queries - Add "Ungrouped" tab to STL page showing packages without a group Time-window auto-grouping: - After album grouping, cluster ungrouped packages within configurable time window (default 5 min, AUTO_GROUP_TIME_WINDOW_MINUTES env var) - Groups named from common filename prefix - Groups created with groupingSource=AUTO_TIME Hash verification after split: - Re-hash split parts and compare to original contentHash - Log error and create SystemNotification on mismatch - Prevents silently corrupted split uploads Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
-- CreateEnum GroupingSource
|
||||
CREATE TYPE "GroupingSource" AS ENUM ('ALBUM', 'MANUAL', 'AUTO_TIME', 'AUTO_PATTERN', 'AUTO_REPLY', 'AUTO_ZIP', 'AUTO_CAPTION');
|
||||
|
||||
-- CreateEnum NotificationType
|
||||
CREATE TYPE "NotificationType" AS ENUM ('HASH_MISMATCH', 'MISSING_PART', 'UPLOAD_FAILED', 'DOWNLOAD_FAILED', 'GROUPING_CONFLICT', 'INTEGRITY_AUDIT');
|
||||
|
||||
-- CreateEnum NotificationSeverity
|
||||
CREATE TYPE "NotificationSeverity" AS ENUM ('INFO', 'WARNING', 'ERROR');
|
||||
|
||||
-- AlterTable: add groupingSource to package_groups
|
||||
ALTER TABLE "package_groups" ADD COLUMN "groupingSource" "GroupingSource" NOT NULL DEFAULT 'MANUAL';
|
||||
|
||||
-- Backfill: mark album-based groups
|
||||
UPDATE "package_groups" SET "groupingSource" = 'ALBUM' WHERE "mediaAlbumId" IS NOT NULL;
|
||||
|
||||
-- CreateTable: system_notifications
|
||||
CREATE TABLE "system_notifications" (
|
||||
"id" TEXT NOT NULL,
|
||||
"type" "NotificationType" NOT NULL,
|
||||
"severity" "NotificationSeverity" NOT NULL DEFAULT 'INFO',
|
||||
"title" TEXT NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"context" JSONB,
|
||||
"isRead" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "system_notifications_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "system_notifications_isRead_createdAt_idx" ON "system_notifications"("isRead", "createdAt");
|
||||
CREATE INDEX "system_notifications_type_idx" ON "system_notifications"("type");
|
||||
@@ -522,6 +522,7 @@ model PackageGroup {
|
||||
name String
|
||||
mediaAlbumId String?
|
||||
sourceChannelId String
|
||||
groupingSource GroupingSource @default(MANUAL)
|
||||
previewData Bytes?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -802,3 +803,45 @@ model KickstarterPackage {
|
||||
@@id([kickstarterId, packageId])
|
||||
@@map("kickstarter_packages")
|
||||
}
|
||||
|
||||
// ── Grouping & Notifications ──
|
||||
|
||||
enum GroupingSource {
|
||||
ALBUM
|
||||
MANUAL
|
||||
AUTO_TIME
|
||||
AUTO_PATTERN
|
||||
AUTO_REPLY
|
||||
AUTO_ZIP
|
||||
AUTO_CAPTION
|
||||
}
|
||||
|
||||
enum NotificationType {
|
||||
HASH_MISMATCH
|
||||
MISSING_PART
|
||||
UPLOAD_FAILED
|
||||
DOWNLOAD_FAILED
|
||||
GROUPING_CONFLICT
|
||||
INTEGRITY_AUDIT
|
||||
}
|
||||
|
||||
enum NotificationSeverity {
|
||||
INFO
|
||||
WARNING
|
||||
ERROR
|
||||
}
|
||||
|
||||
model SystemNotification {
|
||||
id String @id @default(cuid())
|
||||
type NotificationType
|
||||
severity NotificationSeverity @default(INFO)
|
||||
title String
|
||||
message String
|
||||
context Json?
|
||||
isRead Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([isRead, createdAt])
|
||||
@@index([type])
|
||||
@@map("system_notifications")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user