GGThedandClaude Opus 5 e5c29d8113 fix(ops): rendre visibles les pannes silencieuses du bot Discord
OPS-005, OPS-006, OPS-007, OPS-009 et OPS-012. Cinq constats, un motif
commun : le bot pouvait cesser de fonctionner correctement sans que rien,
nulle part, ne le dise.

OPS-006 -- etat en attente ecrit en place
_save_pending ouvrait le fichier de destination en ecriture puis
serialisait dedans : toute interruption laissait un JSON tronque. Et
_load_pending interceptait l erreur de lecture, la journalisait, puis
repartait avec un dictionnaire vide -- toutes les correspondances message
Discord <-> demande disparaissaient, les reactions en cours cessaient
d avoir un effet, et l interface n en montrait rien.

Ecriture par fichier temporaire voisin puis os.replace : la destination
contient l ancien contenu ou le nouveau, jamais la moitie d un des deux.
A la lecture, un fichier illisible est deplace en .corrupt-<horodatage>
plutot qu ecrase, et le message dit ce qui est perdu.

Ecart assume avec la recommandation d audit (« echouer bruyamment ») : le
bot demarre quand meme. Refuser de demarrer supprimerait toutes les
notifications au lieu de celles deja en vol.

OPS-007 -- fuite lente
Les entrees n etaient retirees qu apres reaction. Elles portent desormais
`created_at` et sont purgees au chargement au-dela de 30 jours. Une entree
sans horodatage est conservee : elle precede ce champ, la supprimer serait
deviner son age.

OPS-005 -- planificateur
`coalesce=True`, `misfire_grace_time=3600`, `max_instances=1`. Sans delai
de grace, un redemarrage a 18 h 05 perdait les rappels du jour sans trace ;
sans coalescence, un planificateur en retard envoie un rappel par
occurrence manquee, donc des messages en double.

OPS-009 -- controle d identite asymetrique
handle_one_on_one_approve et _reject comparent depuis toujours le compte
qui reagit au coach destinataire. Les deux gestionnaires de presence ne le
faisaient pas. Meme forme de message, meme risque, un seul verifiait :
c est l asymetrie qui etait le bug.

Au passage : confirmer sa presence a un tryout ecrivait un attribut qui n a
pas de colonne (DB-008, bloque sur Alembic). Le joueur lisait « confirme »
et rien n etait enregistre. Toujours vrai, mais desormais journalise en
warning avec l identifiant concerne.

OPS-012 -- etat du bot dans /health
Le bot tourne dans un fil demon du processus web. Quand ce fil meurt, le
site continue de servir des pages et plus aucune notification ne part.
/health expose maintenant configured / running / connected / pending.
Signale, pas fatal : un club sans rappels Discord est degrade, pas hors
service, et un 503 le sortirait du repartiteur de charge pour ca.

discord_pending.json passe hors suivi git. La regle d ignore etait en place
mais inerte. Consequence non relevee par l audit : le deploiement etant un
miroir de fichiers, chaque livraison ecrasait l etat vivant du serveur par
celui du depot.

13 tests, sans aucun appel a Discord.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-08 18:21:05 -04:00
2026-08-06 14:46:51 -04:00
2026-07-30 09:52:32 -04:00

Plateforme centralisée de tryouts

Security Configuration

Required Environment Variables

Before deploying, create a .env file which integrates everything in the .env.exemple. Ensure you follow the comments of the exemple if you are to use this tool in production.

Security Features Implemented

  • Rate Limiting: Login endpoint limited to 10 requests per minute to prevent brute-force attacks
  • Secure Session Cookies: HTTPSOnly, SameSite=Lax, and Secure flags enabled
  • CSRF Protection: Enabled by default on all forms
  • HTTPS Enforcement: Automatic redirect to HTTPS in production
  • Security Headers: X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, HSTS
  • Open Redirect Prevention: URL validation on login redirect
  • Authorization Checks: Proper ownership validation on all sensitive operations
  • nginx: reverse-proxy and load balancer
  • Waitress WSGI: Production ready WSGI

When true in .env:

  • Forces HTTPS only
  • Forcer secure cookies

App details

Code

  • Full python backend using flask
  • statics are pure HTML and CSS
  • Some js to add logic to styling and showing certain pages/cards

Functionalities

  • User base with sign-ins: Forces users to create an account and register pertinent information for tryouts and teams. The admin can attribute them a role.
  • User-Role-Based Permissions: admin - full acces, coach/manager - access to team management, player - views what he is registered in (no management), scout - view only
  • Tryout Management: manage internal tryout teams, organise internal tryouts matches (3 formats, team vs team, PvP, scrim). Coaches can Evaluate players based on 10 criteria
  • Team Management: manage teams for the season, create matches and practices. When planning a practice there will be a calendar showing player availabitlities slots to help chose a time
  • Coach and Player Availabilities: Allow better planning for the coaches, and for players to book One on Ones with their coach.
  • Player Notes: Coaches can give notes to their players. The players will see them and there is a history which keeps the most recent notes.
  • Team Notes: Coaches can give notes to their teams, where all players from that team can see the note.
  • One on One: Players can request a One on One meeting with their coach. This sends a discord dm to the coach to accept or refuse. The player is then notified of the response.
  • Availabilities: Allow players and coach to enter the moments they are available. Allows for easier practice setup and One on One planning.

Discord Integration

The application supports sending Discord direct messages to coaches when players request One on One sessions, when matches/tryouts/practices are created and a player is in it, and the players get match reminders 24h before a match.

When sending a One on One request, the coach can accept via the platform or react to the discord message to answer the booking request. Same thing with matches and practices, the players can react or answer on the platform.

Setup Instructions

1. Create a Discord Bot (Not needed for UdeS user, the bot already exists)

  1. Go to the Discord Developer Portal
  2. Create a new application
  3. Go to the "Bot" tab and create a bot user
  4. Copy the bot token - this will be your DISCORD_BOT_TOKEN
  5. Enable the "Message Content Intent" under Privileged Gateway Intents (required for sending messages)

2. Add Bot to your server

For the bot to send DMs:

  1. Each user must have the bot added to their Discord server OR be friends with the bot
  2. Users need to add their Discord User ID to their profile:
    • Enable Developer Mode in Discord (User Settings → Advanced → Developer Mode)
    • Right-click on their profile → Copy ID
    • Enter this numeric ID in the "Discord User ID" field in their profile settings

How It Works

When a player submits a One on One request:

  1. The system checks if the coach has a Discord User ID configured
  2. If configured, a direct message is sent to the coach via the Discord bot

Message Format

The Discord DM includes:

  • Player name
  • Team name
  • Requested date and time slot
  • Discussion points (if provided)
  • Link to the application for approval/rejection
  • Two provided reactions to accept or refuse via discord
S
Description
No description provided
Readme
2.3 MiB
Languages
Python 67.9%
HTML 27%
CSS 3.5%
JavaScript 1.6%