Software Requirements Specification (SRS)

FLA Event & Awards Platform β€” plain PHP, modular, subdomain-hosted.
Living document: every feature planned or built gets its use case recorded here
(rule in WORKFLOW.md). View this file in the browser at /docs/srs.
FieldValue
ProductFLA Event & Awards Platform (working title "Event")
URLhttps://event.production1.jugaar.ai (plain 443 HTTPS β€” no ports, no localhost)
StackPHP 8.3 (plain, no framework) Β· MariaDB 10.11 Β· Nginx Β· GD
Version3.0.0 (Ceremony Production System)
StatusDraft β€” living
Last updated2026-08-29

1. Introduction

1.1 Purpose

Define everything the platform must do, in business use-case language, so that:

  • the owner knows exactly what is being built and in which order;
  • any (new) development session can resume work from this file + TODO.md;
  • each feature has one authoritative flow description (linked workflow docs).

1.2 Scope

A modular web platform for events whose flagship capability is public-voted, AI-assessed awards. Branding (name, logo, colors, campaign texts) is managed from an admin Control Panel β€” nothing brand-related is hardcoded. The platform is a single-tenant deployment on its own subdomain.

Out of scope (v1.x): payments/ticketing for paid events (not requested), native apps, multi-tenant SaaS operation.

1.3 Definitions

TermMeaning
ApplicantPerson registering for an award category
GoHGuest of Honor (C-level: CIO etc.) invited/approved to give awards
VoterPublic person who votes via a shared link; verified via LinkedIn
JudgePanel member reviewing applicants in the review board
StaffTeam members (comms, manual entries, ticket replies)
AdminOwner-level access; finalize results, veto, all visibility
Share linkhttps://event.production1.jugaar.ai/v/{public_token} per applicant
Share cardGenerated PNG for social posting (applied / visiting / winner)
Mock modeRunning with simulated AI/LinkedIn/WhatsApp until API keys exist

1.4 References

  • ROADMAP.md β€” milestone plan Β· TODO.md β€” live session handoff
  • docs/WORKFLOWS/*.md β€” step-by-step flows (voter flow, judge flow, …)
  • WORKFLOW.md β€” engineering + git + documentation rules

2. Overall Description

2.1 System context

                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 Public ───────►│  https://event.production1.jugaar.ai  (Nginx :443 β†’ PHP) β”‚
 (browser,      β”‚                                                         β”‚
  mobile)       β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
                β”‚   β”‚ Brandingβ”‚ β”‚ Registrationβ”‚ β”‚Voting β”‚ β”‚ Judges/     β”‚  β”‚
 LinkedIn OAuth β”‚   β”‚ Control β”‚ β”‚ (3 types)  β”‚ β”‚ (70%) β”‚ β”‚ Winners     β”‚  β”‚
 ◄─────────────►│   β”‚ Panel   β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”¬β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
                β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚           β”‚                      β”‚
 MiniMax m3 AI  β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”   β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
 ◄─────────────►│   β”‚ AI gateway (mock/   β”‚   β”‚ Audit log  β”‚             β”‚
                β”‚   β”‚ live)               β”‚   β”‚ (append-only)            β”‚
 WhatsApp API   β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
 ◄─────────────►│              β”‚                                        β”‚
 (later)        β”‚        MariaDB (fla_event)                            β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2.2 Key decisions (locked)

#DecisionValue
D1StackPlain PHP 8.3, modular (src/Core + src/Modules/*), no framework
D2DBMariaDB fla_event (installed host)
D3DeploymentSubdomain https://event.production1.jugaar.ai on plain 443
D4BrandingDB settings table, edited in Control Panel, defaults until configured
D5AIProvider gateway; default driver MiniMax platform model minimax-m3; mock until keyed
D6LinkedInOIDC client; mock fixture in dev
D7WhatsAppAbstract gateway; Null driver (logged no-op) until provider + keys
D8Share cardsGD driver now; AI image driver reserved (ApiCardDriver)
D9Voting math70% aggregate public + 30% board; admin veto absolute (BR-005)
D10DocsRepo .md files are the single source; /docs renders them as webpages
D11ChartsChart.js via CDN + internal JSON endpoints (no build step); ASCII/empty-state fallback without JS

2.3 Assumptions & constraints

  • One person = one registration per event (BR-001); identity anchor is the LinkedIn profile.
  • Voters must authenticate with LinkedIn (other providers may be added later).
  • WhatsApp number is mandatory for award/GoH registrations (BR-007).
  • The platform must keep working without external keys (NFR-08 mock mode).
  • Every sensitive action is audit-logged (NFR-03).

3. Actors

ActorDescriptionAccess
GuestUnauthenticated visitorLanding, docs, public results, vote links
VisitorRegistered attendee"I'm visiting" card, event info, dashboard-lite
ApplicantAward candidate in one categoryOwn votes + voters, AI interview, tickets, share cards
VoterAuthenticated via LinkedInCast vote (+ optional reason) per rules
JudgeAssigned reviewerReview board: profiles, AI stats, approve/disapprove
GoHC-level guest presenting awardsApproval-based registration; profile
StaffTeam supportManual entries, tickets, mass comms, shared dashboards
AdminOwnerEverything incl. toggles, categories, veto, finalize, audit UI
System/AIAutomated actorsAI marking, badge generation, notifications, announcements

4. Business rules

IDRule
BR-001One person may hold exactly one registration per event (DB unique (event_id, user_id)).
BR-002An award applicant cannot also be Guest of Honor in the same event (and vice versa).
BR-003Voting default: one vote per LinkedIn profile per candidate; admin may relax/change per event β€” logged.
BR-004Final score = 70% public-vote share + 30% board score, normalized per category.
BR-005Admin veto is absolute: admin may exclude any applicant at any stage; audit-logged with reason.
BR-006An applicant sees own vote count and voter identities only β€” never others'. Only admin sees the global leaderboard before finalization.
BR-007WhatsApp number is required for award and GoH registrations.
BR-008Registration prefers LinkedIn OAuth; voters must authenticate with LinkedIn.
BR-009Winners are announced by the system only after admin approval + audit lock.
BR-010AI interview: category-scoped questions drawn randomly from the active bank; answers AI-marked; stats attached to the applicant.
BR-011Repeat-candidate surveillance: every registration is scanned against all registrations across events (email, LinkedIn, CNIC-hash, name+WhatsApp, repeat-application). Any match β‡’ flagged + admin alerted; admin confirms (auto-veto) or dismisses.

5. Functional requirements

FR-0100 β€” Platform, Branding & Docs

IDRequirementModule
FR-0101Admin edits branding: name, logo, tagline, primary color, favicon β†’ live everywhereBranding
FR-0102Admin toggles features on/off (per module) without deploysBranding/Admin
FR-0103All repository .md docs rendered as organized webpages under /docsDocs
FR-0104Campaign texts for share cards edited in admin (placeholders {event} {name} {category})Branding
FR-0105Base URL = subdomain on plain 443; absolute_url() used for share linksCore

FR-0200 β€” Events & Categories

IDRequirement
FR-0201CRUD events: name, type (normal / ai / award), dates, venue, status lifecycle
FR-0202CRUD award categories per event: name, description, show/hide (is_active), sort order
FR-0203Categories shown publicly only when active; admin chooses what displays
FR-0205Event cloning: one-click copy of event + categories + question bank as a new draft
FR-0210Event templates: snapshot an event (categories + questions + scoring) as a named reusable template; one-click draft creation from itEvents
FR-0211Calendar export: .ics per public event ("Add to calendar")Events
FR-0212Event package export: admin JSON download (event, categories, questions, registrations, votes incl. removals, winners, snapshots, audit)Events/Admin
FR-0213Recurring events: weekly/monthly + optional repeat-until; next occurrence auto-drafted (categories + question bank copied) when the current one finishes; parent linkageEvents
FR-0204Public events directory (/events) with live + archive sections
FR-0106Maintenance mode (site.maintenance): public site returns 503 with custom message; admin/staff bypass

FR-0300 β€” Registration (v0.4.0)

IDRequirement
FR-0301Two public entry paths: "Register as Visitor" and "Apply for an Award" (separate links OK)
FR-0302LinkedIn OAuth signup preferred; system captures id, name, email, picture
FR-0303Fallback basic form: name, email, WhatsApp (+ passwordless)
FR-0304Award flow: pick category β†’ info β†’ WhatsApp β†’ photo (optional at signup, required before approval; may be completed later on dashboard) β†’ AI interview
FR-0305GoH flow: title/company/bio/photo (optional at signup, required before approval); approval-based; staff may enter manually (incl. government guests)
FR-0305bDecision messages: approve/reject β†’ in-app + email + SMS (log transports) for all types; GoH submit confirmation email+SMS
FR-0306Staff manual entry "on behalf of" for any type (entered_by_user_id)
FR-0307Enforce BR-001/BR-002/BR-007 with clear errors
FR-0308Photo stored under storage/uploads, bound to registration; may be uploaded at signup or later via POST /dashboard/photo; required before approved (single+bulk)
FR-0309Basic (non-LinkedIn) signups get an email-verification link; verified flag tracked
FR-0310GET /verify-email?token=… completes verification; unverified badge visible to admin

FR-0400 β€” AI Engine (v0.5.0)

IDRequirement
FR-0401Question bank per category, admin-managed, active flag
FR-0402Interview session: N random active questions (default 5), one at a time
FR-0403Each answer AI-marked (score 0–100 + feedback); session total + summary
FR-0404Stats shown on applicant dashboard + judges board
FR-0405Non-AI ("normal") events skip the interview entirely (normal registration OK)
FR-0406Provider-swappable gateway; mock mode until key; cost/logging of calls

FR-0500 β€” Public Voting (v0.6.0)

IDRequirement
FR-0501Applicant gets personal share link + dashboard to copy it
FR-0502Vote page: candidate card (photo, name, category, AI summary if enabled)
FR-0503Voter authenticates via LinkedIn before voting (BR-008)
FR-0504Optional one-line reason ("what is this person good at") β€” toggleable per event
FR-0505Enforce voting restrictions; friendly errors; duplicate attempt shown as already-voted
FR-050670/30 weighting engine computes blended score on demand (BR-004)
FR-0507Admin veto action UI (BR-005) with mandatory reason β†’ audit
FR-0508Applicant sees own votes + voters (BR-006); public leaderboard optional/admin-only pre-final
FR-0509Per-event vote-change toggle: when enabled, voters can update reason / move their vote (audited vote.changed); default: votes are final
FR-0510Share links support ?ref= attribution, persisted through OAuth onto the vote row; applicant sees channel breakdown

FR-0600 β€” Share Cards (v0.6.0)

IDRequirement
FR-0601Generate PNG cards: applied / visiting / winner from photo + campaign text
FR-0602GD driver default; AI driver pluggable (cards.driver)
FR-0603Card + share link packaged for LinkedIn/FB posting (Open Graph tags on vote page)
FR-0604Finalist certificate cards (PNG) generated for finalists after results lock
FR-0605Printable certificates (winner/finalist) β€” print/PDF-ready HTML page

FR-0700 β€” Judges Panel (v0.7.0)

IDRequirement
FR-0701Admin creates judge accounts + assigns event/category scope
FR-0702Judges board: list contestants in scope w/ profile, photo, AI stats, media
FR-0703Judge decision per contestant: approve / disapprove / needs info + notes
FR-0704Compiled report β†’ main admin (per category: votes, AI score, judge tallies)
FR-0705Admin can re-issue team passwords (judge/staff): new temp password, forced change on next login, audited
FR-0706Judge rubric: per-review 0–10 scores (innovation/impact/leadership) feed the board score as avg/30; legacy reviews fall back to approval ratio

FR-0800 β€” Dashboards (v0.8.0, starter in v0.2.0)

IDRequirement
FR-0801Applicant: votes over time (chart), voter list (own), AI results, notifications, tickets, share cards
FR-0802Staff: queues (tickets, pending manual entries), comms tools
FR-0803Admin: comprehensive β€” registrations, votes, AI, judges, comms, audit, toggles
FR-0804Reminders/notifications surface on dashboards (FR-1200)
FR-0805Admin graphs: votes-over-time, registration funnel, per-category vote shares, top-10 candidates, AI score distribution β€” Chart.js (CDN) fed by internal JSON endpoints
FR-0806Admin stats coverage: KPI cards with trend deltas (7d/30d) β€” users by role, registrations by type/status, votes cast, AI interviews run, judge reviews done, tickets by status/age, comms delivery rates β€” all filterable by event/category/date
FR-0807Audit tab on admin dashboard: live audit-log feed with filters (actor, action, entity, date) β€” FR-1102 UI

FR-0400 β€” AI Engine (v0.5.0)

IDRequirement
FR-0401Question bank per category, admin-managed, active flag
FR-0402Interview session: N random active questions (default 5), one at a time
FR-0403Each answer AI-marked (score 0–100 + feedback); session total + summary
FR-0404Stats shown on applicant dashboard + judges board
FR-0405Non-AI ("normal") events skip the interview entirely (normal registration OK)
FR-0406Provider-swappable gateway; mock mode until key; cost/logging of calls
FR-0407AI admin insights (v0.5.0+): natural-language summaries per applicant ("judge-ready brief"), weekly event summary for admin ("what changed this week"), vote-anomaly flags (bursts/single-IP clustering summarized by AI). All mock-compatible via the AI gateway

FR-0900 β€” Ticketing & Mass Comms (v0.8.0)

IDRequirement
FR-0901Applicants/visitors open tickets; staff reply in thread; statuses tracked
FR-0902Mass communication to audiences (all/visitors/applicants/goh/category/status)
FR-0903Channels: email first; WhatsApp when provider keys arrive (numbers already collected)
FR-0904Public media/gallery sections per event

FR-1000 β€” Winners (v0.9.0)

IDRequirement
FR-1001Finalize per category: blend 70/30 + judge results β†’ shortlist
FR-1002Admin approves β†’ audit lock β†’ system publishes winners (BR-009)
FR-1003Winner badges + "Winner" share cards auto-generated
FR-1004Public results page + notifications to winners
FR-1005Category results can be un-locked (retract public results, winners→finalist, event→judging) — fully audited; re-lock replaces the snapshot
FR-1006Hall of fame (/hall-of-fame) β€” every winner across finished events
FR-1007Ceremony reveal mode: per-event toggle; locked categories revealed one-by-one (audited winner.revealed); results page, venue screen and API gated until revealed

FR-1100 β€” Audit (v0.9.0)

IDRequirement
FR-1101Append-only audit log (actor, action, entity, ip, meta, time)
FR-1102Admin filter/search UI; no edit/delete of audit rows

FR-1300 β€” Integrity & anti-fraud (v1.1.0)

IDRequirement
FR-1301Signal collection: normalized email, LinkedIn id/URL, CNIC (hash-only, salted SHA-256 β€” plain never stored), name+WhatsApp pair
FR-1302Scan on every registration (public, manual entry, claim) against all events + same-account repeat detection
FR-1303Alerts: duplicate_alerts rows + in-app notification to all admins + audit entry
FR-1304Admin review queue /admin/duplicates: side-by-side comparison β†’ confirm (auto-veto new) or dismiss
FR-1305Visibility: ⚠ dup badge + filter on registrations list, open-alerts KPI on admin overview
FR-1700Data rights: member can download their data as JSON and irreversibly anonymize their account (PII stripped, votes retained detached, photos deleted, audited)
FR-1701Public profiles /profile/{token} (approved applicants + GoH): photo, title/company, bio, LinkedIn + X/IG/FB; contact info stays staff-only
FR-0107Auditor role: read-only team access (overview, audit, registrations, duplicates, winners, system, search); all mutations remain admin/staff-only
FR-0309bCategory capacity + waitlist: optional max_applicants; overflow registrations β†’ waitlisted (notified, audited); admin promotes via approve
FR-0311CSV bulk import: staff upload (name,email,whatsapp,cnic,category,title,company) β†’ on-behalf registrations with per-line error report; audited

FR-1200 β€” Notifications (v0.8.0)

IDRequirement
FR-1201In-app notifications (vote milestones, ticket replies, results)
FR-1202Reminder surface on dashboards; channel escalation (WhatsApp/email) later

6. Use-case library

Full step-by-step flows live in docs/WORKFLOWS/. Here: the contract version
(preconditions β†’ main flow β†’ alternates β†’ postconditions).

UC-01 Configure branding & toggles β€” Admin

  • Pre: admin logged in.
  • Main: open Control Panel β†’ edit name/logo/colors/campaign texts β†’ save β†’ changes live immediately; toggle module features on/off.
  • Alt: restore defaults; invalid color rejected.
  • Post: settings persisted; audit entry written.

UC-02 Manage event & categories β€” Admin

  • Pre: admin. Main: create event (type award) β†’ add categories β†’ set active/order β†’ announce (status).
  • Alt: hide category (existing applicants unaffected); edit anytime.
  • Post: public listing reflects active set.

UC-03 Register as visitor β€” Guest β†’ Visitor Β· flow

  • Pre: event open for registration.
  • Main: open /register/visitor β†’ LinkedIn sign-in (preferred) or basic form (+WhatsApp optional for visitors) β†’ confirm β†’ success page with "I am visiting" card β†’ download/post to social.
  • Alt: existing account β†’ resume; event closed β†’ waitlist message.
  • Post: registration row type=visitor; notification.

UC-04 Apply for an award β€” Applicant + AI Β· flow

  • Pre: active categories; applicant passes BR-001/BR-002 checks.
  • Main: pick category β†’ LinkedIn OAuth β†’ profile imported β†’ basic info + WhatsApp β†’ photo (optional, may complete later on dashboard; required before approval) β†’ AI interview (random category questions, AI-marked) β†’ success page: personal share link + "I have applied" card.
  • Alt: skip AI when event type = normal (BR: normal registration OK); photo may be uploaded later via POST /dashboard/photo; re-try photo upload.
  • Post: registration type=award, status=submitted + ai_session; card PNG.

UC-05 Apply as Guest of Honor β€” GoH / Staff Β· flow

  • Main: /guest-of-honor form (title e.g. CIO, company, bio, photo (optional, may complete later on dashboard), LinkedIn) β†’ pending approval β†’ admin approves (photo required) β†’ listed.
  • Alt (manual): staff uses "enter on behalf" (govt/C-level invitees) β€” flagged entered_by_user_id.
  • Post: registration type=goh, status=pendingβ†’approved; BR-002 enforced.

UC-06 Staff manual entry β€” Staff

  • Main: staff dashboard β†’ "Add on behalf" β†’ choose type β†’ fill form (+upload photo) β†’ confirm β†’ record marked as manual entry.
  • Post: audit entry with staff actor.

UC-07 Cast a vote β€” Voter Β· flow

  • Pre: share link v/{token}; candidate approved; voting window open.
  • Main: open link β†’ LinkedIn auth β†’ (optional) reason β†’ Vote β†’ confirmation + prompt to share.
  • Alt: already voted (per rules) β†’ "already voted" with change-vote policy (default: no duplicates); voting restriction relaxed mode β†’ allowed per admin setting.
  • Post: vote row; candidate count +1; notification to applicant; audit.

UC-08 AI marking & stats β€” System/AI

  • Main: for each answer β†’ score + feedback β†’ session total & summary β†’ attach to applicant β†’ judges/admin see stats. Mock mode deterministic until key (NFR-08).

UC-09 Applicant self-view β€” Applicant

  • Main: dashboard β†’ own vote count, voter identities, AI stats, share link, cards, tickets, notifications.
  • Alt: attempt to view others' totals β†’ denied (BR-006).

UC-10 Judge review β€” Judge Β· flow

  • Main: login β†’ assigned scope β†’ open contestant (profile, photo, AI stats, votes-if-enabled) β†’ decision (approve/disapprove/needs-info) + notes β†’ save.
  • Post: per-category report aggregated for admin.

UC-11 Finalize & announce winners β€” Admin Β· flow

  • Pre: voting closed; judges reported.
  • Main: review blended ranking (70/30) + judges β†’ optional veto (reason) β†’ select winners per category β†’ approve & lock β†’ system announces (public page + notifications) β†’ winner badges + cards generated β†’ winners share.
  • Post: status=winner rows; audit-locked snapshot; public results.

UC-12 Generate share card β€” System

  • Main: on applied/visiting/winner trigger β†’ GD render (photo + campaign text) β†’ stored β†’ shown for download/share. Alt: AI driver later.

UC-13 Support ticket β€” Applicant ↔ Staff Β· flow

  • Main: applicant opens ticket (subject, question, media allowed) β†’ staff replies from queue β†’ status flow (openβ†’pendingβ†’answeredβ†’closed).

UC-14 Mass communication β€” Staff

  • Main: select audience β†’ compose (email; WhatsApp when keyed) β†’ preview recipient count β†’ send β†’ per-recipient status tracked.

UC-15 Review audit log β€” Admin

  • Main: open Audit β†’ filter by actor/action/date β†’ drill into entries (meta JSON).

UC-17 Flag & review a suspected duplicate β€” System + Admin Β· flow

  • Pre: registration submitted (any path incl. manual entry/claim).
  • Main: system scans identity signals across all events β†’ on any match: alert row created, all admins notified, audit entry β†’ admin opens /admin/duplicates β†’ compares side-by-side β†’ Confirm (auto-veto new registration) or Dismiss.
  • Alt: no match β†’ nothing happens; applicant experience unchanged (flag-and-review, never auto-block).
  • Post: queue item resolved; audit trail kept.

UC-16 Admin overview & AI insights β€” Admin

  • Pre: admin logged in (event data exists for meaningful numbers; empty states otherwise).
  • Main: admin home shows KPI cards with trends (7d/30d) β†’ graphs (votes over time, funnel, per-category shares, top candidates, AI score distribution) β†’ tabs: Audit (live filterable feed) β†’ AI Insights (weekly summary, applicant briefs, vote-anomaly flags) β†’ drill into any figure to its underlying list.
  • Alt: AI key missing β†’ insights panel shows mock/sample output with "waiting for AI key" notice (NFR-08).
  • Post: no writes; every query scoped to admin role and covered by the JSON feeds used for charts.

FR-1600 β€” Integrations & venue (v1.5.0)

IDRequirement
FR-1601Webhooks: admin-managed endpoints, event subscriptions (registration.created, vote.cast, winner.locked, duplicate.suspected, or *), HMAC-SHA256 signatures (X-FLA-Signature), delivery log with HTTP status, test ping
FR-1602Venue leaderboard screen /screen/{slug}: auto-refresh (30s), big-display dark theme; public when leaderboard_public/finished, else staff-only
FR-1603CSV exports (admin/staff): registrations & votes, event-scoped, audited (export.csv)
FR-1606Global admin search (/admin/search): one query across registrations (name/email/token), events, tickets and users; header search box on every admin page
FR-0906SMS channel for mass comms (channel=sms) β€” log transport (Pakistan-ready; provider keys plug in)
FR-0907Scheduled comms: optional future send-time; queued recipients; lazy dispatch on staff page + bin/send-scheduled.php for cron
FR-0606QR verification: printable certificates embed a QR β†’ public /cards/{token}/verify page showing live winner/finalist status
FR-0607Certificate numbers (FLA-<year>-<seq>): assigned to winners+finalists at lock; printed on certificates, shown on verify page, searchable
FR-0608GoH card (campaign.goh_text) downloadable by approved Guests of Honor
FR-0620GoH ratings (internal): Seniority/Influence/Relevance 0–100 β†’ avg; global (per person) + per event; effective = event ?? global; roster sorted as suggestion seed; audited goh.rated
FR-1604Bulk admin ops: approve/reject multiple registrations at once; audited per-row
FR-1800Nominations: public /nominate (honeypot + throttled), admin queue β†’ Invite (log email/SMS with signed prefilled link) / Reject; auto-convert on registration (token or email match); webhook nomination.created
FR-1810AI Assistant (/assistant): multi-conversation context-aware chat for admin/staff/judge/auditor; live platform context injected (PII-free for judges); async send, 30 msgs/h/user, audited by length only
FR-1820Web Push: VAPID (ES256) + RFC 8291 encryption in pure PHP; subscriptions per user; admin broadcasts (segments) + auto-push on winner.locked; dead-subscription cleanup; member opt-in on dashboard
FR-1830Internal messaging: team ↔ member threads (inboxes both sides, unread tracking); ai_assisted markers; audit message.sent
FR-1840AI drafting: "Draft with AI" in composer (recipient-aware: role/event/rating) + admin bulk personalized drafts (one intent β†’ per-GoH messages, reviewed before send)
FR-1850Scheduling (both directions): GoH publishes availability slots; staff request/propose; GoH confirms/declines/counter-offers; states open→requested/proposed→confirmed/declined/cancelled; /admin/schedule board; notifications + audit
FR-0180Magic-link login: one-time 15-min email link for members (no LinkedIn needed); throttled; one-time use; no account enumeration
FR-1860People tracking: activity timeline per registrant (/admin/people), engagement score (logins/votes/messages/nominations); anonymous page-view tracking (hashed visitor, public pages only)
FR-1870Vote receipts + hash chain: every vote gets a receipt code (shown to voter) + chained seal; public /verify-vote; chain integrity check on /admin/system
FR-1880AI category fit: applicant describes work β†’ AI suggests best category (mock-safe)
FR-1890Share-link click analytics: pre-auth clicks per candidate link + unique-visitor KPIs on admin overview
FR-2000QR check-in (/admin/checkin): scan/enter token or any cert/vote/profile URL β†’ present; duplicates detected; undo; live counts
FR-2100Presenter assignment + run-sheet: GoH assigned per category (notified); printable timed run-sheet with presenters, winners, cert numbers, confirmed GoH slots
FR-2200Media gallery: members upload photos/video links β†’ staff moderation β†’ live on vote page + event photo wall
FR-2300Ceremony ops (/admin/ceremony): reveal buttons, presenter picks, attendance, screen + run-sheet links on one screen
FR-2400Sponsor wall: per-event sponsors (tier + logo + URL) on event admin + public event page
FR-2500Season report (/admin/report?year=): print/PDF-ready summary β€” events, categories, winners + cert numbers, vote totals
FR-3000MC Dashboard (/mc): dedicated MC role; slide controls (advance/back/skip/goto); stage screen link; run-sheet link
FR-3010Stage Screen (/stage/{slug}): polling-based auto-updating display; renders slide types (logo, anthem, MC intro, GoH, category, winner, sponsor, thanks, blank); multi-GoH layout (1-N presenters side by side)
FR-3020Winner queue: calling order with shield tracking (not_requested β†’ requested β†’ ready / override_blank); reorder (move up/down with reason); called β†’ appeared β†’ appearance count
FR-3030Award Team (/award-team): dedicated role; notified on shield request; confirms "shield ready βœ…" or "not ready ❌"; MC sees status live
FR-3040Admin override: admin can force "blank shield" to unblock queue
FR-3050GoH substitution: mark no-show β†’ replace with substitute (auto-notify); goh_substitutions table; category_presenters updated
FR-3060Self check-in (/self-checkin): attendee enters code/QR β†’ checked in β†’ sees zone/seat + queue position
FR-3070Multi-GoH presenters: category_presenters join table (1-N per category); stage screen auto-adapts layout
FR-3080Ceremony auto-generate: admin one-click generates run-of-show from event data (slides + queue); migration 027
FR-1103Audit CSV export via /admin/export?type=audit
FR-1604Admin 2FA (TOTP, RFC 6238): per-account enable/disable with code confirmation; password→code login challenge

FR-1500 β€” Public API (v1.4.0)

IDRequirement
FR-1501Read-only JSON API: /api/v1/events, /events/{slug}, /events/{slug}/categories, /events/{slug}/winners β€” public data only, no PII, JSON 404s
FR-1502SEO surface: /robots.txt (admin areas disallowed) + dynamic /sitemap.xml
FR-1503Embeddable leaderboard widget /embed/leaderboard/{slug} β€” white-label, 30s auto-refresh, framable (public data only)
FR-0810Vote management: admin browse/remove/restore votes; soft-deleted votes excluded from all tallies; reason mandatory; reversible; audited (vote.removed/vote.restored)Admin
FR-0811Admin onboarding: dismissible getting-started checklist on the overviewAdmin
FR-0812Guided tour: 4-step spotlight walk-through on the admin overview, once per user, skippableAdmin
FR-0620Judges transparency panel: public results page lists the judging board (names, review counts, LinkedIn) post-lockPublic
FR-0720Candidate compare: side-by-side view (max 4) with AI scores, linked from the public leaderboardVoting
FR-0610Public GoH directory: /speakers listing approved guests of honorPublic
FR-1305Hall-of-fame search: full-text ?q= across winners/categories/eventsPublic
NFR-12Async queue: jobs table + minute-cron worker, retries Γ—3 with backoff; Telegram ops alerts (optional)Ops

7. Non-functional requirements

IDRequirement
NFR-01Responsive: mobile-first; all flows usable on phones (voting especially).
NFR-02HTTPS only at https://event.production1.jugaar.ai, plain 443, HSTS once live.
NFR-03Auditability: sensitive actions (login, vote, veto, finalize, manual entries, comms) logged.
NFR-04Performance: p95 page load < 2 s on shared hosting; voting/cards cached where possible.
NFR-05Security: PDO prepared statements, output escaping, CSRF tokens on forms, rate-limit votes/login.
NFR-06Privacy: minimal PII; LinkedIn data only id/name/email/picture; voter list visible to the candidate only (BR-006).
NFR-07Extensibility: modules self-contained under src/Modules/<Name>; core stays lean.
NFR-08Degradability: full flow works in mock mode without any external API key.
NFR-09Availability: graceful error pages; AI/LinkedIn outage never blocks browsing.
NFR-10Backups: nightly DB dump (ops; procedure in HELP.md).
NFR-11Security headers on every response: HSTS (on HTTPS), X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy.
NFR-12Vote rate limiting per IP (default 30/hour, admin-configurable via voting.rate_limit_per_hour), audited as vote.rate_limited.
NFR-13PWA: installable (manifest + icons + service worker; statics cached offline).
NFR-14Team accounts support TOTP 2FA; sensitive flows throttle + audit by default.
NFR-15Ops: system health dashboard (/admin/system) shows DB size, table rows, disk free, storage size, queue depths, backup recency.
NFR-16Public pages cached (file TTL 60–300s; flushed on content-affecting admin mutations).

8. Integrations

ServicePurposeMode nowNeeded from owner
MiniMax platform (platform.minimax.io)AI Q&A marking, summaries, insightsMockAPI key (+ confirm exact m3 model id & base URL)
LinkedIn OIDCRegistration + voter verificationMockApp client id/secret (developer.linkedin.com)
WhatsApp (Meta Cloud API or Twilio)Comms to collected numbersNull (logged)Provider choice + keys
AI image API (TBD)Fancy share cardsGD fallbackAPI key β†’ enables cards.driver=ai

9. Data model (overview)

settings Β· feature_toggles Β· users (admin/staff/judge/applicant/visitor/goh/voter) Β· events Β· categories Β· registrations (+public_token, entered_by_user_id) Β· question_bank Β· ai_sessions Β· ai_answers Β· votes Β· judge_assignments Β· judge_reviews Β· tickets Β· ticket_messages Β· audit_log Β· notifications Β· communications Β· communication_recipients

Key uniques: users.linkedin_id, users.email, registrations(event_id,user_id) (BR-001/002), votes(registration_id,voter_user_id) (BR-003), judge_reviews(registration_id,judge_user_id). DDL: database/migrations/001–009.

10. Open questions

  1. Confirm MiniMax m3 model id + exact base URL; obtain API key (platform.minimax.io).
  2. LinkedIn App credentials (OIDC scopes openid profile email).
  3. WhatsApp provider: Meta Cloud API vs Twilio.
  4. AI image API for share cards (later).
  5. Email sender (SMTP host / transactional service) for comms & notifications.
  6. Allowed vote-change policy (default: votes are final).
  7. Public leaderboard visibility pre-finalization (default: admin-only, BR-006).

Answers get recorded here + in TODO.md when provided.

11. Version history

VersionDateChange
0.1.02026-08-29Initial SRS (docs + scaffold baseline).
1.0.02026-08-29Full platform implemented (all modules live + E2E-verified).
1.1.02026-08-29Duplicate-candidate detection (BR-011, FR-1300, UC-17) + judges anchoring fix.
1.2.02026-08-29Winner un-lock/re-announce flow (FR-1005) + team password reset (FR-0705).
1.3.02026-08-29Polish pack: email verification (FR-0309/0310), vote-change toggle (FR-0509), referral attribution (FR-0510), finalist cards (FR-0604), security headers (NFR-11).
1.4.02026-08-29Public discovery + ops: events directory (FR-0204), hall of fame (FR-1006), printable certificates (FR-0605), public API v1 (FR-1500), robots/sitemap, vote rate limiting (NFR-12), automated backups.
1.5.02026-08-29Integrations & experience: webhooks (FR-1601), venue screen (FR-1602), CSV exports (FR-1603), admin 2FA TOTP (FR-1604), PWA (NFR-13).
1.6.02026-08-29Scale & polish: maintenance mode (FR-0106), bulk ops (FR-1604), audit export (FR-1103), system health (NFR-15), vote guards hardened.
1.7.02026-08-30Photo flexibility B: optional at signup, dashboard upload, approval guard.
1.8.02026-08-30Search & verification: admin global search (FR-1606), SMS channel (FR-0906), QR certificate verification (FR-0606).
2.0.02026-08-30Program growth & ops: nominations (FR-1800), AI assistant (FR-1810), judge rubric (FR-0706), cert numbers (FR-0607), ceremony reveal (FR-1007), capacity+waitlist, scheduled comms (FR-0907), embed widget (FR-1503), data rights (FR-1700), auditor role (FR-0107), event cloning (FR-0205), wa.me chat, public caching (NFR-16).
2.1.02026-08-30Reach: Web Push (FR-1820, pure-PHP crypto), CSV import (FR-0311), waitlist UI, nomination throttle setting.
2.2.02026-08-30Section 2 core: GoH decisions (FR-0305b), GoH card (FR-0608), event-page listing, ratings (FR-0620), public profiles + socials (FR-1701).
2.3.02026-08-30Engage: magic-link login (FR-0180), messaging (FR-1830), AI drafting (FR-1840), scheduling both directions (FR-1850).
2.4.02026-08-30Track & Trust: people tracking (FR-1860), vote receipts+chain (FR-1870), AI category fit (FR-1880), click analytics (FR-1890).
2.5.02026-08-30Section 3 Day-of-Event: check-in (FR-2000), presenters+run-sheet (FR-2100), media gallery (FR-2200), ceremony ops (FR-2300).
2.6.02026-08-30Growth: sponsor wall (FR-2400), season report (FR-2500).
3.0.02026-08-31Ceremony Production System: MC dashboard, stage screen, award team, winner queue + shields, GoH substitution, self check-in, multi-GoH presenters (FR-3000–3080).