Skip to content

Repository files navigation

Copilot Chat Bingo

A browser-based Bingo game for Microsoft 365 Copilot Chat events. Players receive a server-assigned deterministic 3×3 board, complete Copilot tasks, submit proofs, earn keywords for each completed line, and submit those keywords to a shared leaderboard. Event facilitators can manage campaigns, players, organizations, exports, and admin access from an OTP-protected admin portal.

Copilot Chat Bingo application UI

Open source and support

This repository is shared as an open-source sample for organizations and facilitators running Microsoft 365 Copilot adoption events. It is not an official Microsoft support channel unless maintainers state otherwise.

What it does

Copilot Chat Bingo turns event participation into a lightweight challenge loop: players receive a server-assigned pack, complete Copilot Chat tasks, submit proof for each tile, earn line keywords, and submit those keywords to a shared leaderboard. Facilitators use the admin portal to manage campaigns, organizations, players, exports, and admin access.

Features

  • Deterministic assigned boards — pack numbers 1999 always generate the same nine tasks, while the API assigns and rotates packs fairly per player.
  • Proof submission & verification — per-tile validation rules check the player's submitted proof before clearing the tile.
  • Line detection & keyword minting — completing a row, column, or diagonal awards a unique keyword, exactly once per line.
  • Weekly challenges — bonus progression tracked alongside the main board.
  • Shared leaderboard — keyword submissions are stored in Azure SQL and ranked per-organization across all players.
  • OTP-protected admin portal — Azure Communication Services Email sends admin one-time codes for portal login.
  • Cookie-based admin sessions — admin access, refresh, and step-up JWTs are delivered in httpOnly cookies rather than browser-accessible storage.
  • Admin operations — event facilitators can view engagement metrics, export CSV data, manage organizations, manage campaigns, inspect players, and perform safety actions.
  • Admin access management — bootstrap admins come from ADMIN_EMAILS; portal-managed admins are stored in Azure SQL and require a fresh OTP step-up before add/remove changes.
  • Session continuity — reloading the page restores the active board, cleared tiles, earned keywords, and challenge progress from localStorage.
  • Responsive UI — Tailwind CSS v4 layout that remains usable on narrow viewports.

Architecture

flowchart LR
   player[Player browser] --> frontend[Vue 3 SPA\nAzure Static Web Apps]
   admin[Event facilitator] --> frontend
   frontend --> api[Azure Functions API\nNode.js v4]
   api --> sql[(Azure SQL\nplayers, sessions, events, submissions, campaigns, admins)]
  api --> redis[(Azure Managed Redis\ncache-aside API responses)]
   api --> acs[Azure Communication Services Email\nadmin OTP delivery]
   api --> kv[Key Vault\nadmin key, JWT secret, ACS connection string]
  frontend --> sentry[Sentry\napplication errors, traces, logs, metrics, replay]
  api --> sentry
  api --> appi[Application Insights\nAzure platform and runtime diagnostics]
Loading
Layer Responsibility
Vue SPA Player onboarding, board play, keyword submission, activity view, and admin portal screens; Terraform hosts it on Linux App Service, while the manual guide can use Static Web Apps.
Azure Functions API HTTP endpoints for sessions, tile events, submissions, leaderboard, campaign config, admin auth, and admin operations.
Azure SQL Durable storage for game state, progression scoring, organization mappings, campaign settings, OTP hashes, and portal-managed admins.
Azure Managed Redis Optional cache-aside layer for active campaign config, organization domains, and leaderboard responses.
ACS Email Production delivery for admin OTP login and sensitive admin-management step-up verification.
Key Vault Holds generated app secrets referenced by Function App settings.
Sentry Primary application observability for frontend and backend errors, logs, metrics, traces, session replay, releases, and source maps.
Application Insights Azure Functions/App Service platform and runtime diagnostics for host behavior, invocation telemetry, and Azure Portal troubleshooting.
Terraform Provisions Azure infrastructure in Korea Central for regional resources; Azure Communication Services is the only global control-plane exception.

Sentry Issues are reserved for breakage: browser network failures, backend/frontend 5xx responses, unexpected exceptions, local adapter errors, and selected operational failures such as ACS Email. Expected workflow 4xx responses are structured Sentry Logs plus api.client_response metrics by default so normal validation, auth, conflict, not-found, and rate-limit traffic stays visible without becoming incidents. Application Insights remains the Azure platform/runtime diagnostics layer.

App flow

flowchart TD
   start[Player enters name and email] --> hydrate[Load existing player state]
   hydrate --> assign[Create or resume server-assigned pack]
   assign --> board[Render 3x3 Copilot task board]
   board --> proof[Player submits proof for a tile]
   proof --> verify{Proof passes validation?}
   verify -- no --> retry[Show validation guidance]
   retry --> proof
   verify -- yes --> event[Record tile event and update session]
   event --> line{Completed row, column, or diagonal?}
   line -- no --> board
   line -- yes --> keyword[Mint one keyword for that line]
   keyword --> submit[Submit keyword to leaderboard]
   submit --> activity[Leaderboard and activity feed refresh]

   adminLogin[Admin opens #/admin/login] --> otp[Request OTP]
  otp --> session[Verify OTP and receive httpOnly admin cookies]
   session --> portal[Manage dashboard, organizations, campaigns, players, exports]
   portal --> stepup[Fresh OTP step-up for admin access changes]
Loading

Get started

Prerequisites

  • Node.js 20.x or later and npm 10.x
  • Docker Desktop, if you want the fastest full-stack local run
  • Azure Functions Core Tools v4, if you want to run the backend directly with npm start
  • Azure CLI and Terraform only when provisioning or deploying Azure infrastructure

Option 1: run the full stack with Docker Compose

This starts Azure SQL Edge, runs database migrations, starts the backend API, and serves the built frontend.

git clone https://github.com/<your-org-or-user>/m365copilot-game.git
cd m365copilot-game
docker compose up --build

Open http://localhost:8080. The local compose file uses development-only credentials and the bootstrap admin email admin@test.com.

Option 2: run the dev servers manually

Use this path when you want frontend hot reload and local backend debugging.

git clone https://github.com/<your-org-or-user>/m365copilot-game.git
cd m365copilot-game

# Start the local database and apply migrations.
docker compose up db db-init

Create backend/local.settings.json with local-only values:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "SQL_CONNECTION_STRING": "Server=tcp:localhost,1433;Initial Catalog=bingo_db;User ID=sa;Password=<local-sa-password>;Encrypt=false;TrustServerCertificate=true;",
    "ADMIN_KEY": "<local-admin-key>",
    "JWT_SECRET": "<local-jwt-secret-at-least-32-characters>",
    "ADMIN_EMAILS": "admin@test.com",
    "REDIS_CONNECTION_STRING": "redis://localhost:6379",
    "ALLOWED_ORIGINS": "http://localhost:5173,http://localhost:8080",
    "ADMIN_COOKIE_SECURE": "false",
    "ADMIN_COOKIE_SAMESITE": "Lax",
    "NODE_ENV": "development"
  }
}

If you use the root Docker Compose database for manual development, set <local-sa-password> to the local-only SQL password defined in docker-compose.yml. Do not reuse local development values in shared, staging, or production environments.

Redis is optional for local development. Start the Compose redis service or any local Redis on port 6379 to exercise the cache path; omit REDIS_CONNECTION_STRING and the backend will fall back to Azure SQL reads.

Then start the API and frontend in separate terminals:

cd backend
npm ci
npm start
cd frontend
npm ci
npm run dev

Open http://localhost:5173. The Vite dev server proxies /api to the local Functions host.

Verify changes

Use clean installs so local verification matches CI and deployment builds:

cd backend
npm ci
npm run typecheck
npm run build
npm run lint
npm run format:check
npm test

cd ../frontend
npm ci
npm run typecheck
npm run lint
npm run format:check
npm test

For browser functional coverage, run the fast Playwright suite from the frontend project. The suite starts Vite automatically, mocks API responses for deterministic player/admin flows, and checks hardening-sensitive browser contracts such as POST player-state lookup and cookie-backed admin refresh:

cd frontend
npm run e2e

For full-stack smoke coverage, use only a local stack. Start Docker Compose or the backend/frontend dev servers, seed a local admin OTP, then run the gated suite:

docker compose up --build

E2E_ENABLE_ADMIN_OTP_SEED=1 \
ADMIN_E2E_EMAIL=admin@test.com \
ADMIN_E2E_CODE=123456 \
SQL_CONNECTION_STRING='Server=tcp:localhost,1433;Initial Catalog=bingo_db;User ID=sa;Password=BingoTest123!;Encrypt=false;TrustServerCertificate=true;' \
npm run seed:e2e-admin-otp --prefix backend

E2E_BASE_URL=http://localhost:8080 \
E2E_API_BASE_URL=http://localhost:7071/api \
ADMIN_E2E_EMAIL=admin@test.com \
ADMIN_E2E_CODE=123456 \
npm run e2e:fullstack --prefix frontend

Do not point the full-stack suite at shared Azure environments; it creates players, consumes an OTP, and exercises destructive admin boundary checks.

Security notes for contributors

Never commit local secrets or generated deployment files. The repository ignores .env*, backend/local.settings*.json, Terraform state and tfvars, Terraform plans, Azure publish profiles, SWA artifacts, local key/certificate material, and test reports. Use placeholder values in public examples and put real production secrets in Azure App Settings or Key Vault.

Student Ambassador rosters can contain private personal data. Keep real ambassador names and referral codes outside git, for example in an ignored database/private/ JSON file shaped like database/student-ambassador-referrals.example.json. Seed it during migrations with STUDENT_AMBASSADOR_REFERRALS_FILE=database/private/student-ambassador-referrals.json or STUDENT_AMBASSADOR_REFERRALS_JSON='<json-payload>'.

Project layout

Path Description
frontend/ Vue 3 + Tailwind CSS v4 single-page application.
backend/ Azure Functions v4 (Node.js) API — sessions, events, submissions, leaderboard, admin.
database/ Azure SQL migration scripts (schema + seed data).
scripts/ Local Docker Compose database bootstrap scripts.
index.html Legacy single-file build, kept as a rollback target.
openspec/ Spec-driven change history.
DEPLOYMENT.md Step-by-step Azure deployment guide.

Frontend source

Path Description
frontend/src/App.vue Root shell with tabs for Game, Keys, Activity, and Help, plus hash-routed admin views.
frontend/src/components/ UI components (board, panels, modals, HUD).
frontend/src/composables/ Reactive game state, submissions, and toast helpers.
frontend/src/lib/ Pure logic: deterministic RNG, pack generation, verification, keyword minting, API client, storage adapters.
frontend/src/data/ Static data: task bank, line definitions, organization map, storage key constants.

Backend source

Path Description
backend/src/functions/ HTTP-triggered Azure Functions (one file per endpoint).
backend/src/lib/ Shared helpers — SQL connection pool, input validation, admin auth, email delivery.
backend/host.json Azure Functions host configuration (route prefix, logging).

Deploy to Azure

See DEPLOYMENT.md for a complete step-by-step guide covering the manual Azure CLI path. For repeatable deployments with managed identities, Key Vault references, and Terraform-managed infrastructure, use infra/terraform/README.md.

  1. Creating an Azure SQL Database and running migrations
  2. Deploying the Azure Functions API
  3. Deploying the frontend to Azure Static Web Apps
  4. Configuring CORS, environment variables, and custom domains
  5. Post-deploy verification and troubleshooting

API endpoints

Method Route Purpose
POST /api/sessions Create player + game session
PATCH /api/sessions/{id} Update session progress
POST /api/events Record tile events
POST /api/submissions Submit keyword for leaderboard
GET /api/leaderboard Aggregated org rankings
GET /api/player/state Restore player state by email
GET /api/campaigns/active Active campaign configuration
GET /api/organizations/domains Organization domain mappings
POST /api/portal-api/request-otp Send admin login or step-up OTP
POST /api/portal-api/verify-otp Verify admin OTP and issue a session or step-up token
GET /api/portal-api/dashboard Admin metrics, using admin JWT or X-Admin-Key
GET /api/portal-api/export CSV export, using admin JWT or X-Admin-Key
GET /api/portal-api/admins List bootstrap and portal-managed admins
POST /api/portal-api/admins Add/reactivate portal-managed admin; requires step-up OTP
DELETE /api/portal-api/admins/{email} Disable portal-managed admin; requires step-up OTP

The admin portal is available at #/admin/login in the frontend. Login uses the email allow-list from ADMIN_EMAILS plus active rows in admin_users. In production, OTP delivery requires ACS_CONNECTION_STRING and ACS_EMAIL_SENDER; if delivery fails after an OTP is stored, that OTP is invalidated before the API returns an error.

Data & persistence

  • Server-side: game sessions, tile events, keyword submissions, campaign/admin metadata, and portal-managed admin users are stored in Azure SQL. The leaderboard is shared across all players.
  • Client-side: active board state (cleared tiles, earned keywords, challenge progress) and player profile are stored in the browser's localStorage.

Data handling and privacy

Deployers are responsible for the privacy, consent, retention, access control, and compliance obligations for their event or organization. A production deployment can store or process:

  • Player names and email addresses collected during onboarding
  • Gameplay progress, tile events, earned keywords, leaderboard scores, and campaign participation records
  • Admin email addresses, admin access records, and OTP metadata
  • CSV exports that can include player names, email addresses, organization mappings, and score activity
  • Function App, browser, database, and deployment logs that may contain operational identifiers

Protect exported CSV files, logs, Terraform state, local settings, app settings, and deployment credentials according to your organization's data-handling policies. Do not commit production secrets or attendee data to the repository.

Sentry Session Replay is masked by default. An operator can build an explicitly unmasked diagnostic frontend with VITE_SENTRY_REPLAY_UNMASK=true; use that only after reviewing privacy, consent, retention, and Sentry access controls because visible text, input values, and media can be recorded.

Specs & change history

This repository uses OpenSpec for spec-driven development.

When proposing a behavior change, add a new entry under openspec/changes/ with a proposal, design, tasks, and a delta spec. After implementation, archive the change and sync the main spec.

License and trademarks

This project is licensed under the MIT license. See LICENSE.

Release review: before publishing the repository publicly, maintainers should confirm whether the copyright holder in LICENSE should remain Microsoft Singapore or use another Microsoft legal entity.

Microsoft, Microsoft 365, and Copilot are trademarks or registered trademarks of Microsoft Corporation in the United States and other countries. Use of those names in this repository is for descriptive purposes and does not grant trademark rights or imply product support beyond the terms stated in this repository. The software is provided as-is under the license terms.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages