Commit Graph

43 Commits

Author SHA1 Message Date
ca888b4eb7 fix: impersonation navigation uses full page reload
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m59s
Replace router.push() with window.location.href for both
start and end impersonation to ensure the updated JWT cookie
is sent with the new request. Client-side routing can race
with cookie propagation, causing the server to see the old
session and redirect back to admin.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:30:46 +01:00
875c2e8f48 fix: security hardening — block self-registration, SSE auth, audit logging fixes
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Security fixes:
- Block self-registration via magic link (PrismaAdapter createUser throws)
- Magic links only sent to existing ACTIVE users (prevents enumeration)
- signIn callback rejects non-existent users (defense-in-depth)
- Change schema default role from JURY_MEMBER to APPLICANT
- Add authentication to live-voting SSE stream endpoint
- Fix false FILE_OPENED/FILE_DOWNLOADED audit events on page load
  (remove purpose from eagerly pre-fetched URL queries)

Bug fixes:
- Fix impersonation skeleton screen on applicant dashboard
- Fix onboarding redirect loop in auth layout

Observer dashboard redesign (Steps 1-6):
- Clickable round pipeline with selected round highlighting
- Round-type-specific dashboard panels (intake, filtering, evaluation,
  submission, mentoring, live final, deliberation)
- Enhanced activity feed with server-side humanization
- Previous round comparison section
- New backend queries for round-specific analytics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:18:50 +01:00
c8c26beed2 feat: granular file access audit logging (viewed/opened/downloaded)
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Replace single FILE_DOWNLOADED action with three granular actions:
- FILE_VIEWED: inline preview loaded in the UI
- FILE_OPENED: file opened in a new browser tab
- FILE_DOWNLOADED: explicit download button clicked

Add 'purpose' field to getDownloadUrl input (preview/open/download).
All client callers updated to pass the appropriate purpose.
Audit page updated with new filter options and color mappings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:18:28 +01:00
6c52e519e5 feat: impersonation system, semi-finalist detail page, tRPC resilience
- Add super-admin impersonation: "Login As" from user list, red banner
  with "Return to Admin", audit logged start/end, nested impersonation
  blocked, onboarding gate skipped during impersonation
- Fix semi-finalist stats: check latest terminal state (not any PASSED),
  use passwordHash OR status=ACTIVE for activation check
- Add /admin/semi-finalists detail page with search, category/status filters
- Add account_reminder_days setting to notifications tab
- Add tRPC resilience: retry on 503/HTML responses, custom fetch detects
  nginx error pages, exponential backoff (2s/4s/8s)
- Reduce dashboard polling intervals (60s stats, 30s activity, 120s semi)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:55:44 +01:00
cfee3bc8a9 feat: round finalization with ranking-based outcomes + award pool notifications
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m0s
- processRoundClose EVALUATION uses ranking scores + advanceMode config
  (threshold vs count) to auto-set proposedOutcome instead of defaulting all to PASSED
- Advancement emails generate invite tokens for passwordless users with
  "Create Your Account" CTA; rejection emails have no link
- Finalization UI shows account stats (invite vs dashboard link counts)
- Fixed getFinalizationSummary ranking query (was using non-existent rankingsJson)
- New award pool notification system: getAwardSelectionNotificationTemplate email,
  notifyEligibleProjects mutation with invite token generation,
  "Notify Pool" button on award detail page with custom message dialog

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:14:41 +01:00
49e706f2cf feat: applicant onboarding, bulk invite, team management enhancements
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m50s
- Add nationality/institution fields to User model with migration
- Applicant onboarding wizard (name, photo, nationality, country, institution, bio, project logo, preferences)
- Project logo upload from applicant context with team membership verification
- APPLICANT redirects in set-password, onboarding, and auth layout
- Mask evaluation round names as "Evaluation Round 1/2/..." for applicants
- Extend inviteTeamMember with nationality/country/institution/sendInvite fields
- Admin getApplicants query with search/filter/pagination
- Admin bulkInviteApplicants mutation with token generation and emails
- Applicants tab on Members page with bulk select and floating invite bar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:11:11 +01:00
ee2f10e080 Add jury assignment transfer, cap redistribution, and learning hub overhaul
All checks were successful
Build and Push Docker Image / build (push) Successful in 12m19s
- Add getTransferCandidates/transferAssignments procedures for targeted
  assignment moves between jurors with TOCTOU guards and audit logging
- Add getOverCapPreview/redistributeOverCap for auto-redistributing
  assignments when a juror's cap is lowered below their current load
- Add TransferAssignmentsDialog (2-step: select projects, pick destinations)
- Extend InlineMemberCap with over-cap detection and redistribute banner
- Extend getReassignmentHistory to show ASSIGNMENT_TRANSFER and CAP_REDISTRIBUTE events
- Learning hub: replace ResourceType/CohortLevel enums with accessJson JSONB,
  add coverImageKey, resource detail pages for jury/mentor, shared renderer
- Migration: 20260221200000_learning_hub_overhaul

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:50:29 +01:00
6e697cb5d8 Extend Recently Reviewed card to match sibling heights
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
Use flex-1 on the Recently Reviewed card so it stretches to fill the
remaining vertical space in the left column, aligning its bottom with
Juror Workload and Activity Feed. Add className prop to AnimatedCard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:49:15 +01:00
213efdba87 Observer platform: mobile fixes, data/UX overhaul, animated nav
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m41s
- Fix dashboard default round selection to target active round instead of R1
- Move edition selector from dashboard header to hamburger menu via shared context
- Add observer-friendly status labels (Not Reviewed / Under Review / Reviewed)
- Fix pipeline completion: closed rounds show 100%, cap all rates at 100%
- Round badge on projects list shows furthest round reached
- Hide scores/evals for projects with zero evaluations
- Enhance project detail round history with pass/reject indicators from ProjectRoundState
- Remove irrelevant fields (Org Type, Budget, Duration) from project detail
- Clickable juror workload with expandable project assignments
- Humanize activity feed with icons and readable messages
- Fix jurors table: responsive card layout on mobile
- Fix criteria chart: horizontal bars for readable labels on mobile
- Animate hamburger menu open/close with CSS grid transition

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:45:56 +01:00
Matt
51e18870b6 Admin UI audit round 2: fix 28 display bugs across 23 files
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m51s
HIGH fixes (broken features / wrong data):
- H1: Fix roundAssignments → projectRoundStates in project router (7 occurrences)
- H2: Fix deliberation results panel blank table (wrong field names)
- H3: Fix deliberation participant names blank (wrong data path)
- H4: Fix awards "Evaluated" stat duplicating "Eligible" count
- H5: Fix cross-round comparison enabled at 1 round (backend requires 2)
- H6: Fix setState during render anti-pattern (6 occurrences)
- H7: Fix round detail jury member count always showing 0
- H8: Remove 4 invalid status values from observer dashboard filter
- H9: Fix filtering progress bar always showing 100%

MEDIUM fixes (misleading display):
- M1: Filter special-award rounds from competition timeline
- M2: Exclude special-award rounds from distinct project count
- M3: Fix MENTORING pipeline node hardcoded "0 mentored"
- M4: Fix DELIB_LOCKED badge using red for success state
- M5: Add status label maps to deliberation session detail
- M6: Humanize deliberation category + tie-break method displays
- M8: Rename setStageId → setRoundId, "Select Stage" → "Select Round"
- M9: Add missing INVITED/ACTIVE/SUSPENDED to members status labels
- M10: Add ROUND_DRAFT/ACTIVE/CLOSED/ARCHIVED to StatusBadge
- M11: Fix unsent messages showing "Scheduled" instead of "Draft"
- M12: Rename misleading totalEvaluations → totalAssignments
- M13: Rename "Stage" column to "Program" in projects page

LOW fixes (cosmetic / edge-case):
- L1: Use unfiltered rounds array for active round detection
- L2: Use all rounds length for new round sort order
- L3: Filter special-award rounds from header count
- L4: Fix single-underscore replace in award status badges
- L5: Fix score bucket boundary gaps (4.99 dropped between buckets)
- L6: Title-case LIVE_FINAL pipeline metric status
- L7: Fix roundType.replace only replacing first underscore
- L8: Remove duplicate severity sort in smart-actions component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:11:00 +01:00
Matt
8bbdc31d17 Remove download button on mobile, keep only Open in New Tab
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m25s
iOS Safari doesn't support programmatic downloads reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:53:12 +01:00
Matt
9c19661400 Fix iOS download via Content-Disposition header, fix COI gate null check
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Server: presigned GET URLs now include Content-Disposition: attachment header
  when forDownload=true, triggering native browser downloads on all platforms
- Download button uses window.location.href with attachment URL (works on iOS Safari)
- Bulk download uses hidden iframes instead of fetch+blob
- Fix COI gate: getCOIStatus returns null (not undefined) when undeclared,
  so `!== undefined` was always true — changed to `!= null`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 14:56:09 +01:00
Matt
8d28104d51 COI gate + admin review, mobile file viewer fixes for iOS
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m12s
- Integrate COI declaration dialog into jury evaluate page (blocks evaluation until declared)
- Add COI review section to admin round page with clear/reassign/note actions
- Fix mobile: remove inline preview (viewport too small), add labeled buttons
- Fix iOS: open-in-new-tab uses synchronous window.open to avoid popup blocker
- Fix iOS: download falls back to direct link if fetch+blob fails (CORS/Safari)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 14:34:27 +01:00
Matt
0f6473c999 Jury inline doc preview, download fix, category tags, admin eval reset
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m55s
- Replace MultiWindowDocViewer with FileViewer for inline previews (PDF/image/video/Office)
- Fix cross-origin download using fetch+blob instead of <a download>
- Show Startup/Business Concept badge on jury project detail + evaluate pages
- Add admin resetEvaluation procedure with audit logging
- Add dropdown menu on admin assignment rows with Reset Evaluation + Delete
- Make file action buttons responsive on mobile (separate row below file info)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 14:03:38 +01:00
1ec2247295 Make selected expertise tags compact in onboarding
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m17s
Reduced badge size (text-[11px], h-5, tighter padding/gaps) and capped
the selected tags container to max-h-20 with overflow scroll so they
no longer push the rest of the form off-screen on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:34:51 +01:00
Matt
a4ff278db2 Manual save button, file requirement labels, fix config revert bug
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
- Replace auto-save with manual floating save bar that appears when config
  has unsaved changes (Discard / Save Changes buttons). Fixes race condition
  where server sync overwrote local state after toggling switches.
- Show file requirement name (e.g. "Pitch Deck", "Presentation") above each
  document in the All Uploaded Files section on project detail page
- Pass requirement relation data through to FileViewer component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:43:47 +01:00
Matt
cef4709444 Auto-refresh jury dashboard every 30s for live round updates
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m40s
Add AutoRefresh client component that calls router.refresh() on an
interval. Pauses when tab is hidden and refreshes immediately when
tab becomes visible again. Jury dashboard now reflects round
activations within seconds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 13:57:40 +01:00
Matt
f9016168e7 UI fixes: onboarding scroll, expertise tags, jury assignments view
- Fix onboarding card overflow (overflow-hidden → overflow-x-hidden) so
  expertise step can scroll to submit button
- Reduce expertise category list height (max-h-64 → max-h-48)
- Add color dots to expertise tag options matching admin display
- Single-column layout for expertise tags (no truncation)
- Ocean background on onboarding (matches email template)
- Rewrite jury competitions page as assignment-centric grouped by round
- Conditionally show Awards nav item only when juror has award assignments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:48:14 +01:00
Matt
a006c6505c Onboarding: use ocean background image, show full expertise tag names
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m32s
- Replace blue gradient with ocean.png background (matches email templates)
- Display expertise tags one per line with full names (no truncation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:38:26 +01:00
Matt
c9640c6086 Add document analysis: page count, text extraction & language detection
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m7s
Introduces a document analyzer service that extracts page count (via pdf-parse),
text preview, and detected language (via franc) from uploaded files. Analysis runs
automatically on upload (configurable via SystemSettings) and can be triggered
retroactively for existing files. Results are displayed as badges in the FileViewer
and fed to AI screening for language-based filtering criteria.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:09:04 +01:00
6ca39c976b Competition/Round architecture: full platform rewrite (Phases 1-9)
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
Replace Pipeline/Stage system with Competition/Round architecture.
New schema: Competition, Round (7 types), JuryGroup, AssignmentPolicy,
ProjectRoundState, DeliberationSession, ResultLock, SubmissionWindow.
New services: round-engine, round-assignment, deliberation, result-lock,
submission-manager, competition-context, ai-prompt-guard.
Full admin/jury/applicant/mentor UI rewrite. AI prompt hardening with
structured prompts, retry logic, and injection detection. All legacy
pipeline/stage code removed. 4 new migrations + seed aligned.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 23:04:15 +01:00
Matt
b5425e705e Apply full refactor updates plus pipeline/email UX confirmations
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
2026-02-14 15:26:42 +01:00
331b67dae0 Round system redesign: Phases 1-7 complete
Full pipeline/track/stage architecture replacing the legacy round system.

Schema: 11 new models (Pipeline, Track, Stage, StageTransition,
ProjectStageState, RoutingRule, Cohort, CohortProject, LiveProgressCursor,
OverrideAction, AudienceVoter) + 8 new enums.

Backend: 9 new routers (pipeline, stage, routing, stageFiltering,
stageAssignment, cohort, live, decision, award) + 6 new services
(stage-engine, routing-engine, stage-filtering, stage-assignment,
stage-notifications, live-control).

Frontend: Pipeline wizard (17 components), jury stage pages (7),
applicant pipeline pages (3), public stage pages (2), admin pipeline
pages (5), shared stage components (3), SSE route, live hook.

Phase 6 refit: 23 routers/services migrated from roundId to stageId,
all frontend components refitted. Deleted round.ts (985 lines),
roundTemplate.ts, round-helpers.ts, round-settings.ts, round-type-settings.tsx,
10 legacy admin pages, 7 legacy jury pages, 3 legacy dialogs.

Phase 7 validation: 36 tests (10 unit + 8 integration files) all passing,
TypeScript 0 errors, Next.js build succeeds, 13 integrity checks,
legacy symbol sweep clean, auto-seed on first Docker startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 13:57:09 +01:00
b5d90d3c26 Add project reports section and fix mobile overflow issues
- Add project-wide reporting table with scope selector (all rounds / per round)
- Fix horizontal overflow on mobile (body, admin sidebar, logo truncation)
- Make members header and reports tabs responsive with flex-wrap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:08:04 +01:00
bd9cd310fc Remove next-intl localization infrastructure
Strips out the i18n layer (next-intl, message files, language switcher,
provider) to reduce complexity. Nav components now use plain English strings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 14:57:27 +01:00
ce4069bf92 Platform-wide visual overhaul, team invites, analytics improvements, and deployment hardening
UI overhaul applying jury dashboard design patterns across all pages:
- Stat cards with border-l-4 accent + icon pills on admin, observer, mentor, applicant dashboards and reports
- Card section headers with color-coded icon pills throughout
- Hover lift effects (translate-y + shadow) on cards and list items
- Gradient progress bars (brand-teal to brand-blue) platform-wide
- AnimatedCard stagger animations on all dashboard sections
- Auth pages with gradient accent strip and polished icon containers
- EmptyState component upgraded with rounded icon pill containers
- Replaced AI-looking icons (Brain/Sparkles/Bot/Wand2/Cpu) with descriptive alternatives across 12 files
- Removed gradient overlay from jury dashboard header
- Quick actions restyled as card links with group hover effects

Backend improvements:
- Team member invite emails with account setup flow and notification logging
- Analytics routers accept edition-wide queries (programId) in addition to roundId
- Round detail endpoint returns inline progress data (eliminates extra getProgress call)
- Award voting endpoints parallelized with Promise.all
- Bulk invite supports optional sendInvitation flag
- AwardVote composite index migration for query performance

Infrastructure:
- Docker entrypoint with migration retry loop (configurable retries/delay)
- docker-compose pull_policy: always for automatic image refresh
- Simplified deploy/update scripts using docker compose up -d --pull always
- Updated deployment documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 13:20:52 +01:00
98f4a957cc Performance optimization, applicant portal, and missing DB migration
Performance:
- Convert admin dashboard from SSR to client-side tRPC (fixes 503/ChunkLoadError)
- New dashboard.getStats tRPC endpoint batches 16 queries into single response
- Parallelize jury dashboard queries (assignments + gracePeriods via Promise.all)
- Add project.getFullDetail combined endpoint (project + assignments + stats)
- Configure Prisma connection pool (connection_limit=20, pool_timeout=10)
- Add optimizePackageImports for lucide-react tree-shaking
- Increase React Query staleTime from 1min to 5min

Applicant portal:
- Add applicant layout, nav, dashboard, documents, team, and mentor pages
- Add applicant router with document and team management endpoints
- Add chunk error recovery utility
- Update role nav and auth redirect for applicant role

Database:
- Add migration for missing schema elements (SpecialAward job tracking
  columns, WizardTemplate table, missing indexes)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 11:04:26 +01:00
09091d7c08 Jury dashboard compact layout, assignment redesign, auth fixes
- Jury dashboard: collapse zero-assignment state into single welcome card
  with inline quick actions; merge completion bar into stats row; tighten spacing
- Manual assignment: replace tiny Dialog modal with inline collapsible section
  featuring searchable juror combobox and multi-select project list with bulk assign
- Fix applicant invite URL path (/auth/accept-invite -> /accept-invite)
- Add APPLICANT role redirect to /my-submission from root page
- Add Applicant label to accept-invite role display
- Fix a/an grammar in invitation emails and accept-invite page
- Set-password page: use MOPC logo instead of lock icon
- Notification bell: remove filter tabs, always show all notifications

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 01:26:19 +01:00
d787a24921 Observer dashboard extraction, PDF reports, jury UX overhaul, and miscellaneous improvements
- Extract observer dashboard to client component, add PDF export button
- Add PDF report generator with jsPDF for analytics reports
- Overhaul jury evaluation page with improved layout and UX
- Add new analytics endpoints for observer/admin reports
- Improve round creation/edit forms with better settings
- Fix filtering rules page, CSV export dialog, notification bell
- Update auth, prisma schema, and various type fixes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 23:08:00 +01:00
5c4200158f Improve projects UX, settings layout, uppercase names, per-page selector, and fix round deletion
- Fix round deletion FK constraint: add onDelete Cascade on Evaluation.form and SetNull on ProjectFile.round
- Add configurable per-page selector (10/20/50/100) to Pagination component, wired in projects page with URL sync
- Add display_project_names_uppercase setting in admin defaults, applied to project titles across desktop/mobile views
- Redesign admin settings page: vertical sidebar nav on desktop with grouped sections, horizontal scrollable tabs on mobile
- Polish projects page: responsive header with total count, search clear button with result count, status stats bar, submission date column, country display, mobile card file count

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 20:13:47 +01:00
829acf8d4e Add file requirements per round and super admin promotion via UI
Part A: File Requirements per Round
- New FileRequirement model with name, description, accepted MIME types, max size, required flag, sort order
- Added requirementId FK to ProjectFile for linking uploads to requirements
- Backend CRUD (create/update/delete/reorder) in file router with audit logging
- Mime type validation and team member upload authorization in applicant router
- Admin UI: FileRequirementsEditor component in round edit page
- Applicant UI: RequirementUploadSlot/List components in submission detail and team pages
- Viewer UI: RequirementChecklist with fulfillment status in file-viewer

Part B: Super Admin Promotion
- Added SUPER_ADMIN to role enums in user create/update/bulkCreate with guards
- Member detail page: SUPER_ADMIN dropdown option with AlertDialog confirmation
- Invite page: SUPER_ADMIN option visible only to super admins

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 23:01:33 +01:00
e73a676412 Comprehensive platform audit: security, UX, performance, and visual polish
Phase 1: Security - status transition validation, Zod tightening, DB indexes, transactions

Phase 2: Admin UX - search/filter for awards, learning, partners pages

Phase 3: Dashboard - Recent Activity feed, Pending Actions card, quick actions

Phase 4: Jury - assignments progress/urgency, autosave indicator, divergence highlighting

Phase 5: Portals - observer charts, mentor search, login/onboarding polish

Phase 6: Messages preview dialog, CsvExportDialog with column selection

Phase 7: Performance - query optimizations, loading skeletons, useDebounce hook

Phase 8: Visual - AnimatedCard, hover effects, StatusBadge, empty state CTAs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 22:05:01 +01:00
e0e4cb2a32 Reconcile schema with migrations and fix failed migration
- Align schema.prisma with add_15_features migration (15 discrepancies):
  nullability, column names, PKs, missing/extra columns, onDelete behavior
- Make universal_apply_programid migration idempotent for safe re-execution
- Add reconciliation migration for missing FKs and indexes
- Fix message.ts and mentor.ts to match corrected schema field names

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 14:37:32 +01:00
e7c86a7b1b Add dynamic apply wizard customization with admin settings UI
- Create wizard config types, utilities, and defaults (wizard-config.ts)
- Add admin apply settings page with drag-and-drop step ordering, dropdown
  option management, feature toggles, welcome message customization, and
  custom field builder with select/multiselect options editor
- Build dynamic apply wizard component with animated step transitions,
  mobile-first responsive design, and config-driven form validation
- Update step components to accept dynamic config (categories, ocean issues,
  field visibility, feature flags)
- Replace hardcoded enum validation with string-based validation for
  admin-configurable dropdown values, with safe enum casting at storage layer
- Add wizard template system (model, router, admin UI) with built-in
  MOPC Classic preset
- Add program wizard config CRUD procedures to program router
- Update application router getConfig to return wizardConfig, submit handler
  to store custom field data in metadataJson
- Add edition-based apply page, project pool page, and supporting routers
- Fix CSS (invalid sm:fixed-none), Enter key handler (skip textarea),
  safe area insets for notched phones, buildStepsArray field visibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 13:21:26 +01:00
59436ed67a Implement 15 platform features: digest, availability, templates, comparison, live voting SSE, file versioning, mentorship, messaging, analytics, drafts, webhooks, peer review, audit enhancements, i18n
Features implemented:
- F1: Email digest notifications with cron endpoint and per-user frequency
- F2: Jury availability windows and workload preferences in smart assignment
- F3: Round templates with save-from-round and CRUD management
- F4: Side-by-side project comparison view for jury members
- F5: Real-time voting dashboard with Server-Sent Events (SSE)
- F6: Live voting UX: QR codes, audience voting, tie-breaking, score animations
- F7: File versioning, inline preview, bulk download with presigned URLs
- F8: Mentor dashboard: milestones, private notes, activity tracking
- F9: Communication hub with broadcasts, templates, and recipient targeting
- F10: Advanced analytics: cross-round comparison, juror consistency, diversity metrics, PDF export
- F11: Applicant draft saving with magic link resume and cron cleanup
- F12: Webhook integration layer with HMAC signing, retry, and delivery logs
- F13: Peer review discussions with anonymized scores and threaded comments
- F14: Audit log enhancements: before/after diffs, session grouping, anomaly detection, retention
- F15: i18n foundation with next-intl (EN/FR), cookie-based locale, language switcher

Schema: 12 new models, field additions to User, Project, ProjectFile, LiveVotingSession, LiveVote, MentorAssignment, AuditLog, Program
New routers: roundTemplate, message, webhook (registered in _app.ts)
New services: email-digest, webhook-dispatcher
New cron endpoints: /api/cron/digest, /api/cron/draft-cleanup, /api/cron/audit-cleanup
New API routes: /api/live-voting/stream (SSE), /api/files/bulk-download

All features are admin-configurable via SystemSettings or per-model settingsJson fields.
Docker build verified successfully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:31:41 +01:00
699248e40b Implement 10 platform features: evaluation UX, admin tools, AI summaries, applicant portal
Batch 1 - Quick Wins:
- F1: Evaluation progress indicator with touch tracking in sticky status bar
- F2: Export filtering results as CSV with dynamic AI column flattening
- F3: Observer access to analytics dashboards (8 procedures changed to observerProcedure)

Batch 2 - Jury Experience:
- F4: Countdown timer component with urgency colors + email reminder service with cron endpoint
- F5: Conflict of interest declaration system (dialog, admin management, review workflow)

Batch 3 - Admin & AI Enhancements:
- F6: Bulk status update UI with selection checkboxes, floating toolbar, status history recording
- F7: AI-powered evaluation summary with anonymized data, OpenAI integration, scoring patterns
- F8: Smart assignment improvements (geo diversity penalty, round familiarity bonus, COI blocking)

Batch 4 - Form Flexibility & Applicant Portal:
- F9: Evaluation form flexibility (text, boolean, section_header types, conditional visibility)
- F10: Applicant portal (status timeline, per-round documents, mentor messaging)

Schema: 5 new models (ReminderLog, ConflictOfInterest, EvaluationSummary, ProjectStatusHistory, MentorMessage), ProjectFile extended with roundId + isLate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:58:27 +01:00
8d0979e649 Comprehensive platform review: security fixes, query optimization, UI improvements, and code cleanup
Security (Critical/High):
- Fix path traversal bypass in local storage provider (path.resolve + prefix check)
- Fix timing-unsafe HMAC comparison (crypto.timingSafeEqual)
- Add auth + ownership checks to email API routes (verify-credentials, change-password)
- Remove hardcoded secret key fallback in local storage provider
- Add production credential check for MinIO (fail loudly if not set)
- Remove DB error details from health check response
- Add stricter rate limiting on application submissions (5/hour)
- Add rate limiting on email availability check (anti-enumeration)
- Change getAIAssignmentJobStatus to adminProcedure
- Block dangerous file extensions on upload
- Reduce project list max perPage from 5000 to 200

Query Optimization:
- Optimize analytics getProjectRankings with select instead of full includes
- Fix N+1 in mentor.getSuggestions (batch findMany instead of loop)
- Use _count for files instead of fetching full file records in project list
- Switch to bulk notifications in assignment and user bulk operations
- Batch filtering upserts (25 per transaction instead of all at once)

UI/UX:
- Replace Inter font with Montserrat in public layout (brand consistency)
- Use Logo component in public layout instead of placeholder
- Create branded 404 and error pages
- Make admin rounds table responsive with mobile card layout
- Fix notification bell paths to be role-aware
- Replace hardcoded slate colors with semantic tokens in admin sidebar
- Force light mode (dark mode untested)
- Adjust CardTitle default size
- Improve muted-foreground contrast for accessibility (A11Y)
- Move profile form state initialization to useEffect

Code Quality:
- Extract shared toProjectWithRelations to anonymization.ts (removed 3 duplicates)
- Remove dead code: getObjectInfo, isValidImageSize, unused batch tag functions, debug logs
- Remove unused twilio dependency
- Remove redundant email index from schema
- Add actual storage object deletion when file records are deleted
- Wrap evaluation submit + assignment update in
- Add comprehensive platform review document

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 20:31:08 +01:00
8cdf6c9e5e Add unified expertise tag system and round entry notifications
- ExpertiseSelect now fetches tags from database with category grouping
- Tags set by admin during invitation are locked and cannot be removed
- Onboarding merges user-selected tags with admin-preset tags
- MENTOR role now goes through onboarding flow
- Added migration for Round.entryNotificationType column
- Added seed script with ~90 comprehensive expertise tags

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 01:15:21 +01:00
4f0531d2ee Add ExpertiseSelect component for onboarding
Replace database-backed TagInput with a cleaner ExpertiseSelect
component that has predefined ocean conservation expertise areas.
Features a checkbox grid UI that's more user-friendly for onboarding.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 00:56:03 +01:00
0277768ed7 Add notification bell system and MOPC onboarding form
Notification System:
- Add InAppNotification and NotificationEmailSetting database models
- Create notification service with 60+ notification types for all user roles
- Add notification router with CRUD endpoints
- Build NotificationBell UI component with dropdown and unread count
- Integrate bell into admin, jury, mentor, and observer navs
- Add notification email settings admin UI in Settings > Notifications
- Add notification triggers to filtering router (complete/failed)
- Add sendNotificationEmail function to email library
- Add formatRelativeTime utility function

MOPC Onboarding Form:
- Create /apply landing page with auto-redirect for single form
- Create seed script for MOPC 2026 application form (6 steps)
- Create seed script for default notification email settings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 21:30:25 +01:00
90e3adfab2 Implement Prototype 1 improvements: unified members, project filters, audit expansion, filtering rounds, special awards
- Unified Member Management: merge /admin/users and /admin/mentors into /admin/members with role tabs, search, pagination
- Project List Filters: add search, multi-status filter, round/category/country selects, boolean toggles, URL persistence
- Audit Log Expansion: track logins, round state changes, evaluation submissions, file access, role changes via shared logAudit utility
- Founding Date Field: add foundedAt to Project model with CSV import support
- Filtering Round System: configurable rules (field-based, document check, AI screening), execution engine, results review with override/reinstate
- Special Awards System: named awards with eligibility criteria, dedicated jury, PICK_WINNER/RANKED/SCORED voting modes, AI eligibility
- Dashboard resilience: wrap heavy queries in try-catch to prevent error boundary on transient DB failures
- Reusable pagination component extracted to src/components/shared/pagination.tsx
- Old /admin/users and /admin/mentors routes redirect to /admin/members
- Prisma migration for all schema additions (additive, no data loss)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:58:29 +01:00
8fda8deded Add image cropping to avatar upload and show avatars platform-wide
- Add react-easy-crop for circular crop + zoom UI on avatar upload
- Create server-side getUserAvatarUrl utility for generating pre-signed URLs
- Update all nav components (admin, jury, mentor, observer) to show user avatars
- Add avatar URLs to user list, mentor list, and project detail API responses
- Replace initials-only avatars with UserAvatar component across admin pages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:19:28 +01:00
a606292aaa Initial commit: MOPC platform with Docker deployment setup
Full Next.js 15 platform with tRPC, Prisma, PostgreSQL, NextAuth.
Includes production Dockerfile (multi-stage, port 7600), docker-compose
with registry-based image pull, Gitea Actions CI workflow, nginx config
for portal.monaco-opc.com, deployment scripts, and DEPLOYMENT.md guide.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:41:32 +01:00