Centurion
main·commit c2d57cb

Centurion

Transparent, auditable platform for allocating industry-sponsored software projects to student teams through structured voting and server-side spin-draw events. Built for FIT Semester Project allocation at University of Moratuwa.

Web AppEducationEvent Platform

Links

Overview

Centurion (open source as ProjAlloc in knurdz/sp-vote-system) is a transparent, fair, and auditable platform for allocating real-world industry software projects to student teams. It replaces spreadsheet-and-email matching with a structured digital workflow: admins publish sponsored projects, team leaders vote, and winners are chosen in live spin-draw events with results locked atomically in the database.

The system was built for AI Batch 24 at the Faculty of Information Technology, University of Moratuwa, as part of the Semester Project (SP) module where companies sponsor real software problems and university teams compete to win them.

Centurion Mission Log — project browse and voting dashboard

The Problem

Every semester, FIT coordinates industry-sponsored projects where student teams apply to work on a company's software problem. Historically, allocation relied on spreadsheets, email threads, and manual matching—opaque, slow, and dispute-prone. Centurion gives every team the same information, timestamped votes, unpredictable server-side winner selection, and a permanent audit trail.

How It Works

  1. Admins publish projects with descriptions, tech stacks, team size, and voting deadlines.
  2. Team leaders browse and vote for at most one project each (withdraw and recast allowed before the deadline).
  3. Voting closes automatically via pg_cron when deadlines pass (with client-side effective-status fallback).
  4. Live spin-draw — on a Zoom call, admins review candidates and trigger a spin; the animated wheel is visual only.
  5. Results archivelock_spin_result() picks the winner in PostgreSQL, writes immutable spin_logs, assigns the project, and exposes outcomes to everyone.
Admin: projects & teams
Voting phase (leaders)
Spin draw (server-side)
Results archive (public)

Key Features

  • Structured voting with one vote per team, enforced by database constraints and RLS while projects are in voting status.
  • Live spin events with Framer Motion wheel UI; winner selection runs in lock_spin_result() using ORDER BY gen_random_uuid() inside a single transaction.
  • Immutable audit logspin_logs stores all candidates (JSONB) and the winner with no UPDATE/DELETE policies.
  • Role-based accessadmin, leader, and viewer assigned on first Google sign-in via a database trigger (never set from the frontend).
  • Admin panel — project and team CRUD, CSV team import, dashboard stats, and spin trigger pages.
  • Public transparency — anonymous users can browse projects and archived results; vote counts exposed via secured RPC where configured.
  • Leader workspace — personal view for assigned project context after allocation.

Fairness Guarantees

PropertyMechanism
RandomnessPostgres gen_random_uuid() ordering for winner selection
AtomicityFull spin outcome in one SQL transaction
IdempotencySecond spin attempt raises “result already recorded”
No client tamperingWinner chosen in the database, not in JavaScript
Race safetyFOR UPDATE locks on project and spin event rows
Timely closepg_cron closes voting when deadlines pass

Security Model

Row Level Security is enabled on every table with deny-by-default policies. Admins are seeded via admin_emails; leaders match teams.leader_email. Only VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY reach the browser—the anon key is constrained entirely by RLS. Admin routes re-fetch profile role from Supabase on navigation rather than trusting cached client state.

Stack

LayerTechnology
FrontendReact 19, Vite, TypeScript
StylingTailwind CSS, custom design tokens
AnimationFramer Motion (spin wheel)
BackendSupabase (PostgreSQL 15)
AuthSupabase Auth — Google OAuth 2.0
StateZustand (auth)
HostingVercel (frontend) + Supabase Cloud
Updates15-second polling (no WebSocket subscriptions)

Status

Live at centurion.knurdz.org. Source on GitHub at commit c2d57cb on main. The repository includes full Supabase migrations, RLS policies, cron jobs, and setup documentation for other departments or batches.