Add calendar export, SEO, error monitoring, backups, audit trail, and a starter test suite
Six site improvements picked from a "what could be better" review, plus a Jest test suite covering the two areas with the trickiest money-handling history in this project (early-bird pricing tranches, donation-leg accounting): - "Add to calendar" .ics download on event pages and in confirmation emails - sitemap.xml, robots.txt, and Open Graph/Twitter metadata for public pages - Sentry error monitoring (backend + frontend), a no-op until SENTRY_DSN is set - Nightly local pg_dump backups with a Site Settings tab to browse/trigger/download - Admin audit trail for refunds, donations, manual registrations, event and settings changes, and staff-initiated cancellations - Jest tests reproducing and guarding against the 1.8.0 tranche-pricing bug and the 1.4.2 donation-balance-inflation bug Wallet passes (Google/Apple) were scoped out of this round — Apple Wallet needs a paid Apple Developer account the project doesn't have yet, and the user preferred shipping both together later rather than Google alone now. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AdminAuditAction" AS ENUM ('refund_created', 'donation_assigned', 'donation_unassigned', 'registration_created_manual', 'registration_cancelled', 'event_created', 'event_updated', 'event_deleted', 'settings_updated');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AdminAuditLog" (
|
||||
"id" TEXT NOT NULL,
|
||||
"actorId" TEXT,
|
||||
"actorRole" TEXT NOT NULL,
|
||||
"action" "AdminAuditAction" NOT NULL,
|
||||
"targetType" TEXT NOT NULL,
|
||||
"targetId" TEXT,
|
||||
"metadata" JSONB,
|
||||
"ip" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AdminAuditLog_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AdminAuditLog_actorId_createdAt_idx" ON "AdminAuditLog"("actorId", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AdminAuditLog_action_createdAt_idx" ON "AdminAuditLog"("action", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AdminAuditLog_targetType_targetId_idx" ON "AdminAuditLog"("targetType", "targetId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AdminAuditLog" ADD CONSTRAINT "AdminAuditLog_actorId_fkey" FOREIGN KEY ("actorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -86,6 +86,7 @@ model User {
|
||||
personCashCountsEntered EventCashupPersonCount[] @relation("EventCashupPersonCountEnteredBy")
|
||||
|
||||
securityEvents SecurityEvent[]
|
||||
adminAuditLogs AdminAuditLog[] @relation("AdminAuditActor")
|
||||
}
|
||||
|
||||
model Event {
|
||||
@@ -344,6 +345,39 @@ model SecurityEvent {
|
||||
@@index([userId, createdAt])
|
||||
}
|
||||
|
||||
enum AdminAuditAction {
|
||||
refund_created
|
||||
donation_assigned
|
||||
donation_unassigned
|
||||
registration_created_manual
|
||||
registration_cancelled
|
||||
event_created
|
||||
event_updated
|
||||
event_deleted
|
||||
settings_updated
|
||||
}
|
||||
|
||||
// Append-only audit trail for admin/supervisor-initiated actions with money or
|
||||
// data-integrity impact — separate from SecurityEvent (user-account-security-specific,
|
||||
// fixed enum). Nullable FK with SetNull mirrors SecurityEvent's pattern so entries
|
||||
// survive account close/anonymization.
|
||||
model AdminAuditLog {
|
||||
id String @id @default(uuid())
|
||||
actorId String?
|
||||
actor User? @relation("AdminAuditActor", fields: [actorId], references: [id], onDelete: SetNull)
|
||||
actorRole String
|
||||
action AdminAuditAction
|
||||
targetType String
|
||||
targetId String?
|
||||
metadata Json?
|
||||
ip String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([actorId, createdAt])
|
||||
@@index([action, createdAt])
|
||||
@@index([targetType, targetId])
|
||||
}
|
||||
|
||||
model EventAttachment {
|
||||
id String @id @default(uuid())
|
||||
eventId String
|
||||
|
||||
Reference in New Issue
Block a user