{
 "_comment": "Sorti-Ka — Registre des sources d'événements (province de Québec). Auteur : Simon-Pierre Boucher — contact@spboucher.ai",
 "sources": [
  {
   "id": "sitq",
   "name": "SIT Québec — Ministère du Tourisme",
   "url": "https://www.donneesquebec.ca/recherche/dataset/sit-quebec-evenements",
   "type": "donnees-ouvertes",
   "extraction": "API JSON (Tourinsoft, syndication publique) — dates, géoloc, thèmes, contacts ; le flux ne publie ni heure (T00:00:00 partout) ni tarif ni photo (re-vérifié 2026-08-25) → enrichissement incrémental des SITES OFFICIELS des événements : og:image + og:description (filtre anti-slogan <30 car.), cache versionné v2, plafond SITQ_IMG_MAX=200/sync (90 % des sites livrent une vraie description)",
   "acces_legal": "Licence Creative Commons 4.0 (Données Québec) — API officielle publiée par le Ministère du Tourisme",
   "couverture": "Événements touristiques, toutes les régions du Québec",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "montreal",
   "name": "Ville de Montréal — Événements publics",
   "url": "https://donnees.montreal.ca/dataset/evenements-publics",
   "type": "donnees-ouvertes",
   "extraction": "API CKAN datastore_search (JSON, paginée) — venue = emplacement (si vrai nom de lieu) ou titre_adresse ; address = adresse_principale + adresse_secondaire ; le jeu de données ne publie pas l'heure → heure locale captée dans le JSON-LD des fiches montreal.ca (« startDate »:\"…T19:30:00-04:00\") lors de l'enrichissement og:image incrémental (cache, plafond MTL_IMG_MAX/sync). MAJ 2026-08-25 : plafond MTL_IMG_MAX doublé (600/sync), collecte complète puis priorisation jamais-visités/date proche — convergence atteinte : image 100 % et heure 99 % des événements à venir",
   "acces_legal": "Licence CC BY 4.0 (donnees.montreal.ca) — attribution : Ville de Montréal",
   "couverture": "Événements municipaux, île de Montréal",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "lepointdevente",
   "name": "Le point de vente — billetterie québécoise",
   "url": "https://lepointdevente.com/billets",
   "type": "billetterie",
   "extraction": "pages de liste HTML rendues serveur (paginées), parse des cartes (titre, date FR + heure « 17 août 2026, 20h00 » → start_time, salle, ville, image) + fiches détail /billets/<id> incrémentales (cache data/lepointdevente_cache.json, 150 fiches/sync, re-visite 7 j) : description og:description, heure précise, tarifs JSON réels via /plugins/rates/<id> → price_min/price_label/is_free ; artistes extraits des titres par patrons sûrs seulement (« Artiste - Salle », « X en concert »). MAJ 2026-08-25 (fiches v2, LPDV_DETAIL_MAX=150/sync) : adresse civique en microdonnées schema.org (streetAddress + addressLocality, 84 % des fiches) → géocodage aval",
   "acces_legal": "robots.txt : « User-Agent: * / Allow: * » — GET throttlés, identification honnête, lien direct vers chaque billetterie",
   "couverture": "Concerts, humour, théâtre, festivals — partout au Québec (~2 500 événements à venir)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "laval",
   "name": "Ville de Laval — Calendrier des activités",
   "url": "https://www.donneesquebec.ca/recherche/dataset/calendrier-des-activites",
   "type": "donnees-ouvertes",
   "extraction": "fichier JSON officiel (Données Québec) — EventDate/EndDate publiés en UTC (vérifié 2026-08) → convertis en date + heure locales Québec (minuit local = « toute la journée », pas d'heure) ; détection du préfixe « ANNULÉ - » du titre → statut cancelled (Phase 2)",
   "acces_legal": "Licence CC 4.0 (Données Québec) — Ville de Laval",
   "couverture": "Activités municipales, Laval",
   "cadence": "horaire (watcher PM2)",
   "statut": "morte-a-la-source",
   "decision": "2026-08-19 (audit Phase 1 + Phase 2) : le jeu ouvert est MORT À LA SOURCE — 293 enregistrements, EventDate max 2025-12-09, plus aucun événement futur publié depuis fin 2025 alors que le connecteur tourne sans erreur (41 runs verts). Le connecteur reste branché (archivage naturel du stock + réveil automatique si la Ville republie), mais la source ne compte plus comme active. REMPLACEMENT prévu en Phase 3 : calendrier vivant laval.ca / Tourisme Laval (voir 04-SOURCES-CANDIDATES de l'audit).",
   "note": " REMPLACÉE 2026-08-19 (Phase 3) par la source « lavalweb » (calendrier vivant laval.ca)."
  },
  {
   "id": "sherbrooke",
   "name": "Ville de Sherbrooke — Calendrier des événements",
   "url": "https://www.sherbrooke.ca/fr/culture-sports-et-loisirs/calendrier-des-activites",
   "type": "municipal",
   "extraction": "la page rend TOUT le calendrier dans window['TRANSFER_CACHE'] (JSON embarqué, CMS Maruche) → 1 seule requête, ~270 événements (nom, périodes en UTC → date + heure locales Québec, gratuité `payant`, catégories, clientèles, images)",
   "acces_legal": "page municipale publique (référencée sur Données Québec) — GET direct, identification honnête",
   "couverture": "Événements municipaux et culturels, Sherbrooke (Estrie)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "longueuil",
   "name": "Ville de Longueuil — Événements (nouveau portail)",
   "url": "https://longueuil.quebec/fr/evenements",
   "type": "municipal",
   "extraction": "page liste rendue serveur (portail Nuxt) — cartes <article class=\"event__item\"> : <time datetime> (date + heure locales, début/fin), titre, lien, extrait ; enrichissement par fiche incrémental (cache data/longueuil_cache.json, 30 fiches/sync, re-visite 30 j) : adresse civique, code postal, municipalité depuis l'état Nuxt (address_line1/postal_code/locality) ; GPS via le géocodeur central",
   "acces_legal": "portail municipal public, rendu serveur — GET throttlés 0,8 s, identification honnête",
   "couverture": "Événements municipaux, Longueuil (Montérégie)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif",
   "note": "Remplace le jeu Données Québec « evenements » périmé (dernière date 2017-03, vérifié 2026-08-17) par le portail vivant longueuil.quebec."
  },
  {
   "id": "eventbrite",
   "name": "Eventbrite — billetterie libre-service (Québec)",
   "url": "https://www.eventbrite.ca/d/canada--montreal/all-events/",
   "type": "billetterie",
   "extraction": "pages de découverte publiques /d/<lieu>/all-events/?page=N (7 lieux QC pondérés : Montréal, Québec, Laval, Gatineau, Sherbrooke, Longueuil, Trois-Rivières) — window.__SERVER_DATA__ livre 20 résultats/page : nom, résumé, date + heure locales, salle géocodée (lat/lng, adresse, code postal), image, catégories (tags Eventbrite*), URL ; prix par fiche détail /e/<slug> incrémentale (JSON-LD AggregateOffer lowPrice/highPrice CAD ; cache data/eventbrite_cache.json, 150 fiches/sync, re-visite 7 j) ; en ligne exclus, filtre region=QC strict",
   "acces_legal": "robots.txt « User-agent: * » n'interdit ni /d/ ni /e/ (seuls /directory/, checkout et endpoints privés) — GET throttlés 0,8 s, identification honnête, lien direct vers chaque fiche",
   "couverture": "Événements communautaires, ateliers, festivals, affaires — grandes villes du Québec",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "cantonsdelest",
   "name": "Tourisme Cantons-de-l'Est — calendrier officiel (ATR Estrie)",
   "url": "https://www.cantonsdelest.com/evenements",
   "type": "tourisme-regional",
   "extraction": "page 1 SSR + pagination AJAX POST /event/more {_csrf, ids, offset} jusqu'à épuisement (~596 occurrences, CDE_PAGE_MAX=120) — carte : lien /evenements/<id>/<slug>/<idDate>, catégorie, titre, image, « Ville | date FR (abrégés janv./févr. gérés) » ; fiches incrémentales (CDE_FICHE_MAX=40/sync, re-visite 7 j) : JSON-LD Event (dates précises, description, adresse, CP) + GPS data-lat/lng ; recoupement SITQ par dedup_key",
   "acces_legal": "pages publiques de l'ATR, rendu serveur — GET throttlés 0,8 s, identification honnête, lien vers la fiche originale",
   "couverture": "Festivals, spectacles, événements — Cantons-de-l'Est (Estrie)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "saguenay",
   "name": "Ville de Saguenay — Événements culturels",
   "url": "https://www.donneesquebec.ca/recherche/dataset/sag_evenements-culturels",
   "type": "donnees-ouvertes",
   "extraction": "CSV (Données Québec)",
   "acces_legal": "Licence CC 4.0 (Données Québec)",
   "couverture": "Saguenay",
   "cadence": "n/d",
   "statut": "abandonnee",
   "note": "Jeu de données périmé — dernière date d'événement : 2022-06 (vérifié 2026-08-17). REMPLACÉE 2026-08-19 (Phase 3) par la source « saguenaysorties » (portail sorties.saguenay.ca)."
  },
  {
   "id": "repentigny",
   "name": "Ville de Repentigny — Événements",
   "url": "https://www.donneesquebec.ca/recherche/dataset/evenement-sur-le-territoire-de-la-ville",
   "type": "donnees-ouvertes",
   "extraction": "CSV (Données Québec)",
   "acces_legal": "Licence CC 4.0 (Données Québec)",
   "couverture": "Repentigny (Lanaudière)",
   "cadence": "n/d",
   "statut": "abandonnee",
   "note": "Jeu de données périmé — dernière date d'événement : 2021-09 (vérifié 2026-08-17)"
  },
  {
   "id": "evenko",
   "name": "evenko — grands concerts et festivals",
   "url": "https://evenko.ca/fr/evenements",
   "type": "promoteur",
   "extraction": "API /api/search (proxy Algolia) — format percé : GET ?body=base64({params:[query,options],lang:'fr-CA'}), filters entity_type:evenko_show, ~5 requêtes/sync ; heure locale du spectacle via show_time (epoch → America/Montreal, respect de hide_show_time) ; artistes = champ headliners explicite ; gratuité : champ free (sondé null sur 100 % des hits, 2026-08) + étiquettes « gratuit » (event_tag/promotional_tag) ; aucun montant exposé par l'index. MAJ 2026-08-25 : aucun montant exposé (index Algolia complet 660 hits + JSON-LD des pages événement sans price) — prix uniquement chez Ticketmaster (connecteur ticketmaster, priceRanges)",
   "acces_legal": "robots.txt : Allow /api/search* (explicite) — lien billets = URL Ticketmaster officielle",
   "couverture": "Grands concerts (Centre Bell, Place Bell, MTELUS…), festivals (Osheaga, ÎleSoniq…)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "atuvu",
   "name": "Atuvu.ca — calendrier culturel",
   "url": "https://atuvu.ca/",
   "type": "agregateur",
   "extraction": "sitemaps XML publics + fiches HTML en GET direct (repli Scrapfly seulement sur défi Cloudflare) — cache versionné v2 : heure précise (92 % des fiches v2), tarifs après mise en vente (46 %), séances multiples le même jour suffixées -HHMM ; re-visite roulante 14 j des fiches à venir, plafond ATUVU_MAX_FETCH/sync",
   "acces_legal": "robots.txt : Allow / + sitemap public",
   "couverture": "Sorties culturelles, Grand Montréal",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "lavitrine",
   "name": "La Vitrine culturelle",
   "url": "https://www.lavitrine.com/",
   "type": "billetterie",
   "extraction": "sitemap.xml + fiches rendues serveur (carrousel dates/heures/salles, description, og:image) + pages REPRÉSENTATION (…/<ficheId>/<dateId>) : JSON-LD Event complet → adresse, code postal, GPS bruts de la source (100 % constaté), prix billetterie (73 %) ; date+heure locales prises du fil d'Ariane (le startDate JSON-LD est en UTC et change de jour — piège évité) ; incrémental versionné v3, plafond LV_MAX_FETCH/sync",
   "acces_legal": "robots.txt : Allow / + Content-Signal search=yes, use=reference — usage index + lien vers la fiche originale",
   "couverture": "Spectacles et sorties culturelles, Grand Montréal",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "brossard",
   "name": "Ville de Brossard — Calendrier des événements",
   "url": "https://brossard.ca/calendrier-des-evenements/",
   "type": "municipal",
   "extraction": "API REST WordPress publique /wp-json/wp/v2/city-event (JSON paginé, ~400 fiches) + dates/heures par fiche : bannière « Cet événement aura lieu le … » (fiches ville) ou JSON-LD Event (fiches biblio.brossard.ca) — cache incrémental data/brossard_cache.json, 80 fiches/sync, re-visite 7 j ; repli : date entre parenthèses dans le titre",
   "acces_legal": "API REST WordPress publique (aucune authentification) — GET throttlés 0,8 s, identification honnête",
   "couverture": "Événements municipaux et de bibliothèque, Brossard (Montérégie)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "ticketmaster",
   "name": "Ticketmaster — Discovery API (Québec)",
   "url": "https://developer.ticketmaster.com/products-and-docs/apis/discovery-api/v2/",
   "type": "billetterie",
   "extraction": "SANS clé (mode par défaut) : scraping léger des pages découverte publiques www.ticketmaster.ca/discover/<ville>?page=N (montreal, quebec-city, gatineau) — l'état Next.js (__NEXT_DATA__, requête serveur cityEvents) livre 20 événements/page : titre, date UTC + fuseau → date/heure locales, salle géolocalisée (lat/lng), adresse, code postal, ville, URL billetterie, catégorie majeure, plan de salle (image) ; plafonds TM_MAX_EVENTS=360 / TM_PAGES_PER_CITY=8 ; Scrapfly ASP sans render_js en secours anti-bot ; aucun prix publié dans ce flux → jamais inventé. REPLI AUTOMATIQUE : si TICKETMASTER_API_KEY apparaît dans .env, bascule sur la Discovery API v2 officielle (priceRanges, attractions → artistes, images 16:9) — identifiants identiques, zéro doublon.",
   "acces_legal": "pages découverte publiques rendues serveur — robots.txt n'interdit pas /discover/ (seuls /api/ismds/*) ; GET throttlés 1 s, lien direct vers la billetterie officielle ; API officielle (clé gratuite) utilisée dès qu'une clé est fournie",
   "couverture": "Grands spectacles, sports et concerts — Montréal/Laval/Brossard, Québec, Gatineau",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif",
   "note": "Fonctionne sans clé (scraping découverte). TICKETMASTER_API_KEY optionnelle : active le mode API riche (prix, artistes, images)."
  },
  {
   "id": "bandsintown",
   "name": "Bandsintown — dates de concerts par artiste",
   "url": "https://rest.bandsintown.com/",
   "type": "agregateur",
   "extraction": "API publique /artists/{artiste}/events (app_id format widget « js_www.sorti-ka.com », testé accepté 2026-08 ; un app_id arbitraire simple est refusé) — pas de recherche géographique : on interroge les artistes déjà extraits de la base (evenko/lepointdevente/ticketmaster, événements à venir), plafond 100 artistes/sync avec rotation et cache data/bandsintown_cache.json (re-visite 3 j) ; on ne garde que les dates au Québec (venue.region=QC) : datetime local (date+heure), salle géolocalisée, lineup → artistes, free → gratuité, lien billets. MAJ 2026-08-25 : image d'artiste reprise de n'importe quel événement de la réponse, sinon 1 GET de repli sur le profil /artists/<nom> (100 % constaté sur l'échantillon) ; rotation BIT_ARTIST_MAX/sync",
   "acces_legal": "API publique Bandsintown (app_id d'identification) — usage index + lien vers la fiche originale",
   "couverture": "Concerts au Québec des artistes en tournée connus de la base",
   "cadence": "horaire (watcher PM2, rotation d'artistes)",
   "statut": "actif"
  },
  {
   "id": "gatineau",
   "name": "Ville de Gatineau — Calendrier officiel",
   "url": "https://calendrier.gatineau.cloud",
   "type": "municipal",
   "extraction": "API JSON interne POST /calendrier/json/evenements.aspx (1 requête) — dates UTC→locale, lieux et images ~100 %. RÉACTIVÉE 2026-08-25 (l'abandon visait l'open data, mort ; le calendrier applicatif est vivant)",
   "acces_legal": "application municipale publique, robots: all",
   "couverture": "Gatineau (Outaouais)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "levis",
   "name": "Ville de Lévis — Calendrier des événements",
   "url": "https://levis.ca/fr/calendrier-des-evenements",
   "type": "municipal",
   "extraction": "GraphQL public du site (queryToken de lecture extrait de la page à chaque run). RÉACTIVÉE 2026-08-25 (l'abandon visait le WAF sur GET — l'API GraphQL publique passe)",
   "acces_legal": "API du site municipal public, jeton public, robots.txt permissif",
   "couverture": "Lévis (Chaudière-Appalaches)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "terrebonne",
   "name": "Ville de Terrebonne — Calendrier",
   "url": "https://terrebonne.ca/calendrier-des-evenements/",
   "type": "municipal",
   "extraction": "API REST wp-json/wp/v2/event via Scrapfly (Cloudflare), 3-5 appels/sync. RÉACTIVÉE 2026-08-25",
   "acces_legal": "API publique du site municipal ; anti-bot contourné avec volumes minimes",
   "couverture": "Terrebonne (Lanaudière)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "lavalweb",
   "name": "Ville de Laval — calendrier vivant laval.ca",
   "url": "https://www.laval.ca/calendrier-activites/",
   "type": "municipal",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = WordPress rendu serveur, pagination ?findstr[group]=events&findstr[page]=N (58 pages × ~8 cartes ≈ 460 activités à venir mesurées) ; l'API REST /wp-json/wp/v2/events (764 fiches) ne publie PAS la date de l'événement → listes SSR retenues ; volume mesuré ~460 ; couverture = activités municipales/culturelles/sportives Laval ; robots.txt lu : Disallow /wp-admin/ seulement ; effort ●●.",
   "extraction": "listes SSR paginées (cartes .event-item : date FR « 18 août 2026 | 18 h » → date + heure, titre, lieu, lien, image lazy) + fiches détail incrémentales (cache data/lavalweb_cache.json, LAVALWEB_FICHE_MAX/sync, re-visite 7 j) : og:description ; GPS via annuaire de salles + géocodeur",
   "acces_legal": "robots.txt laval.ca : Disallow /wp-admin/ seulement — pages calendrier publiques, GET throttlés 0,5 s, identification honnête",
   "couverture": "Activités municipales, Laval (remplace le jeu Données Québec mort à la source depuis 2025-12)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "outaouais",
   "name": "Tourisme Outaouais — calendrier des événements (ATR)",
   "url": "https://tourismeoutaouais.com/calendrier-des-evenements",
   "type": "tourisme-regional",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = site Astro, la page calendrier embarque TOUT le calendrier dans les props sérialisées de l'îlot CalendrierDesEvenements (162 événements dont 25 futurs mesurés) — 1 GET/sync ; l'API GraphQL admin.tourismeoutaouais.com exige un jeton (403) ; robots.txt lu : Allow / ; effort ●.",
   "extraction": "props JSON de l'îlot Astro (1 GET, tout le calendrier) + fiches internes /attraits/<slug> des événements À VENIR, incrémentales (OUT_FICHE_MAX/sync, re-visite 7 j) : description, adresse+ville (div.address), site web officiel ; ni heure ni tarif → jamais inventés",
   "acces_legal": "robots.txt : User-agent: * / Allow: / — GET direct throttlé 0,8 s, identification honnête, lien vers la fiche/site officiel",
   "couverture": "Festivals et événements, Outaouais (337 fiches seulement au baseline régional)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "lanaudiere",
   "name": "Tourisme Lanaudière — événements (ATR)",
   "url": "https://lanaudiere.ca/fr/evenements-lanaudiere",
   "type": "tourisme-regional",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = CMS Umbraco, liste SSR limitée à ~10 cartes (44 résultats annoncés, reste en JS) → passage par le SITEMAP officiel (83 URLs de fiches fr mesurées) ; fiches structurées (member-title-1-1 : titre, plage de dates FR, municipalité) + og:image Tourinsoft + og:description ; robots.txt lu : Disallow /*? (aucune URL à paramètres requêtée) + Crawl-delay 2 s (respecté : GET séquentiels 2,1 s) ; effort ●●.",
   "extraction": "sitemap.xml (1 GET, ~85 fiches FR) → fiches incrémentales (LAN_FICHE_MAX/sync, re-visite 7 j, cache v2, Crawl-delay 2 s honoré) : en-tête member-title (titre, plage FR, municipalité), description expandable-intro, adresse+CP member-coords, organisateur, site web member-website, audience « Clientèle admise », og:image",
   "acces_legal": "robots.txt : Disallow /*? + Crawl-delay: 2 — respectés à la lettre (aucun paramètre d'URL, 2,1 s entre GET), identification honnête",
   "couverture": "Festivals et événements, Lanaudière",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "saguenaysorties",
   "name": "Sorties Saguenay — portail événementiel de la Ville",
   "url": "https://sorties.saguenay.ca/",
   "type": "municipal",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = portail SSR de la Ville de Saguenay motorisé par les données La Vitrine (médias lvc-medias.lavitrine.com) ; pagination POST /ajax/plus (36 séances/lot, ~300-400 séances mesurées entre offset 0 et 500) ; détails POST /ajax/details (description + adresse) ; chaque carte = une séance horodatée (date + heure + ville + salle) ; robots.txt : non publié (page de maintenance) → volumes modestes et throttle 0,8 s ; effort ●●. Remplace le CSV Données Québec mort (2022-06).",
   "extraction": "POST /ajax/plus paginé (SAG_BATCH_MAX lots) : discipline, date FR, heure, titre, « Ville, Salle », image, detail-id → une fiche PAR séance ; détails incrémentaux POST /ajax/details (cache data/saguenaysorties_cache.json, SAG_DETAIL_MAX/sync, re-visite 7 j) : description, adresse civique",
   "acces_legal": "portail public municipal — POST throttlés 0,8 s, identification honnête, lien fiche officielle /festivals?id=<id> ; recoupement lavitrine/lepointdevente géré par dedup_key",
   "couverture": "Spectacles, expositions, festivals — Saguenay et environs (Saguenay–Lac-Saint-Jean)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "bassaintlaurent",
   "name": "Tourisme Bas-Saint-Laurent — événements (ATR)",
   "url": "https://www.bassaintlaurent.ca/fr/quoi-faire/evenements/",
   "type": "tourisme-regional",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = WordPress (Bedrock) rendu serveur, 27 cartes complètes sur la liste (titre, plage de dates FR, municipalité, image) ; fiches avec GPS exact embarqué + og:description ; robots.txt lu : rien d'interdit sur /fr/ ; volume mesuré 27 ; couverture = BSL (168 fiches seulement au baseline) ; effort ●.",
   "extraction": "liste SSR (1 GET, cartes .card--type-event, garde-fou ajax-load-more__end-page) + fiches incrémentales (BSL_FICHE_MAX/sync, re-visite 7 j, cache v2) : window.locations JSON → adresse civique, ville, CP, GPS exact, site web ; description longue « À propos » (fallback og:description)",
   "acces_legal": "pages publiques de l'ATR — GET throttlés 0,8 s, identification honnête, lien fiche originale",
   "couverture": "Festivals et événements, Bas-Saint-Laurent",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "quebecanimee",
   "name": "Québec animée — Ville de Québec",
   "url": "https://animee.ville.quebec.qc.ca/activites/",
   "type": "municipal",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = portail municipal SSR ; la liste /activites/ porte TOUT en attributs data- (date-debut/date-fin ISO, arrondissement, catégories, prix « Gratuit ») : 126 séances / 73 activités mesurées, 1 GET ; fiches pour description/lieu ; le calendrier général ville.quebec.qc.ca n'expose pas de flux structuré (vérifié) ; effort ●. Comble l'absence de source municipale/gratuite de la 2ᵉ ville (inventaire Capitale-Nationale ~100 % billetteries).",
   "extraction": "liste HTML rendue serveur + fiches détail incrémentales (QA_FICHE_MAX/sync, cache v2) : heure via boutons data-date/data-heure (62 %), salle réelle .lieu-nom (74 %, zéro bruit), adresse civique .lieu-adresse (72 %) pour le géocodage aval ; venue/heures des entrées v1 muselés (bruit « Lieux » du menu) en attendant le backfill",
   "acces_legal": "site municipal public rendu serveur — GET throttlés 0,8 s, identification honnête, lien fiche officielle",
   "couverture": "Activités gratuites/à faible coût, Ville de Québec (Capitale-Nationale)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "placedesarts",
   "name": "Place des Arts — calendrier multi-salles",
   "url": "https://www.placedesarts.com/programmation",
   "type": "salle-de-spectacle",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = Craft CMS rendu serveur ; /programmation liste 97 spectacles (6 salles) ; chaque fiche embarque #eventbannerdata + #eventGTM (JSON : titre, salle, producteur, discipline, plage de dates) + barre latérale des représentations avec heure ET PRIX RÉELS (« 33 $ à 97,50 $ ») — 23 séances mesurées sur la fiche sonde ; robots.txt lu : Disallow /cpresources/ /vendor/ /cache/ seulement ; effort ●●. Meilleure candidate unitaire de la famille « salles » (audit §C).",
   "extraction": "liste /programmation (1 GET) → fiches /evenement/<slug> incrémentales (cache data/placedesarts_cache.json, PDA_FICHE_MAX/sync, re-visite 7 j) : une fiche Sorti-Ka PAR représentation (date + heure + prix réels), salle précise, producteur → organisateur, discipline → catégories",
   "acces_legal": "robots.txt : Disallow /cpresources/ /vendor/ /cache/ seulement — GET throttlés 0,8 s, identification honnête, lien billetterie officielle ; recoupement lavitrine/evenko géré par dedup_key",
   "couverture": "Spectacles des 6 salles de la Place des Arts, Montréal (~97 spectacles, plusieurs centaines de séances)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "lhjmq",
   "name": "LHJMQ — matchs des équipes québécoises",
   "url": "https://theqmjhl.ca/",
   "type": "sport",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : accès constaté = API HockeyTech « modulekit » (lscluster.hockeytech.com, JSON, clé publique de la ligue embarquée dans ses propres sites) — saison 2026-27 : 580 matchs mesurés dont ~384 à domicile dans 12 villes QC (Chicoutimi, Baie-Comeau, Rimouski, Rouyn-Noranda, Val-d'Or, Gatineau, Shawinigan, Drummondville, Victoriaville, Boisbriand, Sherbrooke, Québec) ; date + heure + aréna structurés ; 2 GET/sync ; effort ●. Fort levier d'équilibre régional (Côte-Nord, Abitibi, BSL…).",
   "extraction": "API modulekit (view=seasons puis view=schedule) : matchs à domicile au Québec seulement → titre « LHJMQ : Visiteur c. Receveur », date + heure locales, aréna, ville, statut annulé si publié ; prix non publié → jamais inventé",
   "acces_legal": "flux JSON public qui motorise le site officiel de la ligue — usage index + lien fiche de match officielle (theqmjhl.ca/gamecentre/<id>), GET throttlés 1 s, identification honnête",
   "couverture": "~384 matchs/saison à domicile au Québec, 12 villes dans 10 régions",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "sallesjsonld",
   "name": "Salles de spectacle — moteur générique JSON-LD Event",
   "url": "https://grandtheatre.qc.ca/programmation",
   "type": "salle-de-spectacle",
   "evaluation": "ÉVALUATION 2026-08-19 (avant connexion) : moteur configurable (data/salles_jsonld.json, patron stores.json de fabri-ka) pour la longue traîne des salles qui publient schema.org/Event sur leurs fiches. Sondage 2026-08-19 : AVEC Event JSON-LD = Grand Théâtre de Québec (108 fiches listées), Théâtre du Trident, Théâtre Capitole (via gestev.com) ; SANS (écartées de la config, re-sonder plus tard) = Palais Montcalm, Le Diamant, Impérial Bell, MTelus/Corona/Club Soda (evenko, déjà couverts), Petit Champlain / Albert-Rousseau (plateforme JS « pages/collections ») ; robots.txt lu salle par salle avant ajout ; effort ●● (moteur) puis ● par salle.",
   "extraction": "par salle configurée : page(s) de programmation → liens de fiche (motif regex) → fiches incrémentales (cache data/sallesjsonld_cache.json, SALLES_FICHE_MAX/sync partagé, re-visite 7 j) → blocs JSON-LD @type Event (nom, dates horodatées, salle, adresse, offres → prix, statut, image) ; heure « T00:00:00 » traitée comme placeholder. Vague 2 2026-08-25 : 17 salles configurées (+13 validées live : Théâtre Denise-Pelletier, MBAM, MNBAQ, Musée de la civilisation, Pointe-à-Callière, Cinémathèque québécoise, TOHU, Spect'Art Rimouski, Hector-Charland, Amphithéâtre Cogeco, Premier Acte, Maison de la littérature, Chasse-galerie Lavaltrie) ; liste du Trident réparée (page d'accueil) ; ~40 salles sondées et écartées (sans JSON-LD, heures faussées ou SSR intermittent — consignées dans le _comment de la config)",
   "acces_legal": "robots.txt vérifié PAR SALLE avant ajout à la config (consigné dans data/salles_jsonld.json) — GET throttlés 0,8 s, identification honnête, lien fiche originale",
   "couverture": "Longue traîne des salles de spectacle QC (amorce : Grand Théâtre de Québec, Trident, Capitole — Capitale-Nationale)",
   "cadence": "horaire (watcher PM2, incrémental)",
   "statut": "actif"
  },
  {
   "id": "mauricie",
   "name": "Tourisme Mauricie — calendrier des événements (ATR)",
   "url": "https://tourismemauricie.com/evenements",
   "type": "tourisme-regional",
   "extraction": "API JSON interne du thème (GET /wp-json/acolyte/v1/get-events-data?lang=fr&page=N, ~174 événements : titre, url, ville, salle, catégories, date FR, GPS, images) + fiches détail incrémentales (JSON-LD Event : date ISO, adresse, description ; cache, MAU_FICHE_MAX=12, re-visite 7 j) ; région par la VILLE (l'ATR couvre des villes du Centre-du-Québec). RÉHABILITÉE 2026-08-25 (écartée Phase 3 pour rendu JS — l'endpoint XHR interne est percé)",
   "acces_legal": "API REST WordPress publique (aucune auth), robots.txt sans interdiction — GET throttlés, UA honnête",
   "couverture": "Mauricie (+ villes limitrophes du Centre-du-Québec)",
   "cadence": "quotidienne",
   "statut": "actif"
  },
  {
   "id": "laurentides",
   "name": "Tourisme Laurentides — calendrier des événements (ATR)",
   "url": "https://www.laurentides.com/evenements/",
   "type": "tourisme-regional",
   "extraction": "API REST /wp-json/wp/v2/mec-events (~228 fiches : titre, description, image) via auto-escalade anti-bot (WAF 403 → Scrapfly ASP) ; dates+heures réelles, tarif, salle et adresse via fiches détail MEC incrémentales pilotées par « modified » (cache, LAU_FICHE_MAX=10/sync). RÉHABILITÉE 2026-08-25 (écartée Phase 3 pour WAF)",
   "acces_legal": "API REST publique ; WAF contourné par proxy/Scrapfly avec requêtes throttlées et plafonnées — UA honnête, lien vers la fiche originale",
   "couverture": "Laurentides",
   "cadence": "quotidienne (backfill des fiches ~3 semaines, puis incrémental)",
   "statut": "actif"
  },
  {
   "id": "gaspesie",
   "name": "Tourisme Gaspésie — événements (ATR)",
   "url": "https://www.tourisme-gaspesie.com/fr/festival-et-evenements/",
   "type": "tourisme-regional",
   "extraction": "Scrapfly (asp, country=ca, sans render_js) : liste (1 crédit) + fiches incrémentales (GASP_FICHE_MAX/sync, re-visite 14 j, cache v2) — titre h1, plage FR, og:description/og:image + JSON-LD Organization → GPS exact, adresse/ville/CP structurés, site web officiel",
   "acces_legal": "Contenu public de l'ATR ; WAF contourné avec modération (budget ≤ 9 crédits Scrapfly/sync, consigné Phase 4), attribution + lien vers la fiche officielle",
   "couverture": "Gaspésie–Îles-de-la-Madeleine",
   "cadence": "horaire (watcher PM2) — cache 14 j, ~2 fiches re-visitées/j",
   "statut": "actif",
   "note": "RÉACTIVÉE 2026-08-21 (Phase 4) : la vague Scrapfly consignée annoncée en Phase 3. Ancienne URL /evenements-gaspesie.html morte (404) → /fr/festival-et-evenements/ (28 fiches, ~6 datées à l'amorce)."
  },
  {
   "id": "tuxedobillet",
   "name": "Tuxedo Billet — billetterie québécoise multi-tenants",
   "url": "https://www.tuxedobillet.com/",
   "type": "billetterie",
   "extraction": "Acteur Apify maison gorgeous_thistle/ka-tuxedo (Playwright, proxy résidentiel CA, code versionné dans apify/ka-tuxedo/) : les tenants <org>.tuxedobillet.com sont des SPA Angular sur Firebase (RTDB verrouillée, 401 même avec jeton anonyme) → rendu navigateur obligatoire. 1 run/TUX_TTL_HOURS (20 h), 29 tenants QC configurés dans data/tuxedo_tenants.json (ville vérifiée). Liste sans heure ni prix → jamais inventés. MAJ 2026-08-25 : fiches /main/<slug> rendues Scrapfly render_js (TUX_FICHE_MAX=20/sync, re-visite 7 j, version v2 = mois janv./févr. compris, +71 événements) : 1 Event par séance datée avec HEURE, statut COMPLET→soldout, catégorie, description. Prix et adresse non publiés (choix des sièges seulement) → jamais inventés. 35 tenants QC (+6 : chateauscenes, azimutdiffusion, culture-umontreal, mcgillathletics, osjm, lesaintjean) ; 10 tenants à liens /Web/ incompatibles consignés dans le _comment du fichier tenants",
   "acces_legal": "Billetteries publiques ; rendu navigateur modéré (1 page/tenant/run, ~1 run par jour), lien d'achat vers la fiche officielle du tenant",
   "couverture": "29 salles/diffuseurs QC : Théâtre Outremont, Le Gesù, Centre Pierre-Péladeau, FTA, FIMAV, Espace Théâtre (Mont-Laurier), L'Anglicane (Lévis), Chandler, Lac-Mégantic, Îles-de-la-Madeleine…",
   "cadence": "quotidienne (TTL 20 h dans le watcher horaire)",
   "statut": "actif",
   "note": "RÉACTIVÉE 2026-08-21 (Phase 4) : l'apex reste vide mais les tenants vivent. Première source consommée via un acteur Apify (billetterie dure à crawler). Énumération des tenants non exhaustive — compléter via Serper/config."
  },
  {
   "id": "clubs-pros",
   "name": "Clubs professionnels (CF Montréal, Alouettes, Rocket, Victoire…)",
   "url": "https://www.cfmontreal.com/",
   "type": "sport",
   "extraction": "n/d",
   "acces_legal": "n/d",
   "couverture": "Montréal/Laval (MLS, LCF, AHL, LPHF)",
   "cadence": "n/d",
   "statut": "abandonnee",
   "note": "ÉCARTÉE 2026-08-19 (Phase 3) : les matchs à domicile passent déjà par les billetteries connectées (evenko/ticketmaster : Canadiens 74 fiches, Remparts 31…) — des connecteurs de ligue dédiés (MLS/LCF/AHL) apporteraient surtout des doublons pour ~150 fiches nettes/an. La LHJMQ, elle, est connectée (vrai levier régional). À revisiter si un besoin statut/heure officiel apparaît."
  },
  {
   "id": "monteregie",
   "name": "Tourisme Montérégie — événements (ATR)",
   "url": "https://www.tourisme-monteregie.qc.ca/membre/categorie/quoi-faire/festivals-et-evenements/",
   "type": "tourisme-regional",
   "extraction": "API REST WP /wp-json/wp/v2/cpt_event (per_page=100) + taxonomie /event-categorie (1 GET → catégories brutes) — titre, description (content, fallback excerpt), plage FR, GPS ACF, site web, image ; fiches incrémentales (MTG_FICHE_MAX/sync, re-visite 7 j) : JSON-LD Event → adresse, ville, CP",
   "acces_legal": "API REST WordPress publique (aucune auth), robots.txt sans interdiction sur /wp-json/ — GET throttlés 0,8 s, UA honnête",
   "couverture": "Montérégie (~78 fiches à venir, vérifié 2026-08-21)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "centreduquebec",
   "name": "Tourisme Centre-du-Québec — événements (ATR)",
   "url": "https://tourismecentreduquebec.com/evenements/",
   "type": "tourisme-regional",
   "extraction": "liste rendue serveur (1 GET, ~9 fiches) ; fiches incrémentales (CDQ_FICHE_MAX=10/sync, re-visite 7 j, cache v2) : champs <small> Adresse/Ville/Entreprise (→ organisateur), description event_details_row, « Programme » → catégories brutes, og:image. Href « site web » vide à la source ; ni heure, ni GPS, ni tarif → jamais inventés",
   "acces_legal": "Site public de l'ATR, robots.txt sans interdiction — GET throttlés 0,8 s, UA honnête",
   "couverture": "Centre-du-Québec (première source de la région — 0 fiche avant connexion ; ~10 fiches)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "chaudiereappalaches",
   "name": "Tourisme Chaudière-Appalaches — festivals et événements (ATR)",
   "url": "https://chaudiereappalaches.com/planifier-votre-sejour/ete-automne/festivals-et-evenements/",
   "type": "tourisme-regional",
   "extraction": "liste SSR paginée (?listpage=1..3) → fiches incrémentales (CHA_FICHE_MAX=12/sync, re-visite 7 j, cache v2) : JSON-LD Event complet (dates ISO, description, adresse, ville, CP, GPS, images) + payload « const HwSheet » → site web officiel et tarif textuel (price_label brut) ; heure non publiée (openingPeriods.hasHours=false)",
   "acces_legal": "Site public de l'ATR, robots.txt sans interdiction sur /planifier-votre-sejour/ — GET throttlés 0,8 s, UA honnête",
   "couverture": "Chaudière-Appalaches (~36 fiches à venir, vérifié 2026-08-21)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "ticketacces",
   "name": "TicketAcces.net — billetterie régionale québécoise",
   "url": "https://www.ticketacces.net/fr/portail/index.cfm",
   "type": "billetterie",
   "extraction": "HTML ColdFusion (cp1252) : annuaire complet des organisations du portail (filtre Québec — 12 orgs NB + 1 ON exclues) + calendrier AGRÉGÉ en 4 GET : 1 Event par représentation datée (titre, date+heure FR, salle, ville, image). Fiches incrémentales (TA_DETAIL_MAX=47/sync = 1 par hôte, re-visite 7 j, version de parse « v ») : og:description, ADRESSE CIVIQUE de la salle (ville suffixée retirée → géocodage aval), prix plancher (les « 0,00 $ » écartés). Crawl-delay 120 s/hôte honoré",
   "acces_legal": "Billetterie publique, robots.txt sans interdiction sur le portail (vérifié 2026-08-21) ; GET throttlés 1 s, UA honnête, cookie de détection ColdFusion géré par session, lien d'achat vers la fiche officielle",
   "couverture": "47 organisations QC — dont 14 en Abitibi-Témiscamingue (Agora des Arts, Théâtre du cuivre, culture Val-d'Or/Amos/La Sarre/Malartic, Théâtre du Rift…), Bas-Saint-Laurent (Océanic, 3L), Côte-Nord (Drakkar), Charlevoix (Domaine Forget), Nord-du-Québec (Lebel-sur-Quévillon)… ~1 300 séances (vérifié 2026-08-21)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "ovation",
   "name": "Réseau Ovation — billetterie québécoise multi-salles",
   "url": "https://reseau.ovation.ca/",
   "type": "billetterie",
   "extraction": "Sous-site mobile m.ovation.ca (HTML rendu serveur, AUCUN anti-bot) : par organisation (codes base36 validés par balayage, config data/ovation_orgs.json), /fr/Search/AllEvents paginé (?pageNumber=N) → 1 eventId = 1 représentation ; fiches fragment EventDescription (≈5 Ko, OVA_FICHE_MAX=40/sync) : date pleine FR + heure, catégories, ARTISTES (liens EventsByPerformer), description, salle + adresse + ville + code postal. Prix non exposé → jamais inventé. MAJ 2026-08-25 : prix NON PUBLIÉS (pages Event mobile+desktop sans aucun montant ni JSON-LD offers ; tarifs uniquement sous /event/tickets, Disallow robots.txt avec /api/) → jamais requêté, jamais inventé ; re-balayage des organisations sans nouveauté",
   "acces_legal": "Billetterie publique sans auth ; GET throttlés 0,7 s, UA honnête, lien d'achat vers la fiche officielle",
   "couverture": "26 organisations 100 % QC : Salle Albert-Rousseau, Petit Champlain, Diffusion Saguenay, Gatineau (Odyssée, Jean-Despréz), Vieux Terrebonne, Palace de Granby, Vieux Clocher Magog/Waterloo, La Tuque, Festival Western de St-Tite, clubs LHJMQ/LNAH…",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "ticketpro",
   "name": "Ticketpro — billetterie canadienne (tenants Québec)",
   "url": "https://www.ticketpro.ca/",
   "type": "billetterie",
   "extraction": "API JSON publique de la nouvelle plateforme SPA par tenant (<org>.ticketpro.ca/api/v1/pages, aucun anti-bot ni rendu JS) : 1 fiche par spectacle avec titre, artiste, description, image, lieu complet (adresse, ville, code postal, lat/lng), toutes les dates horodatées, tags et drapeaux cancelled/soldout → 1 Event par (page, date à venir). 6 tenants QC dans data/ticketpro_tenants.json (tproqc agrège la province mais pas tprotsd), dédup inter-tenants par id de page. Lieux de restauration (soupers-spectacles St-Denis) et musée à créneaux exclus par config. startingPrice toujours 0 → aucun prix émis. MAJ 2026-08-25 : startingPrice vide dans la liste MAIS tarifs réels publics en 2 GET/spectacle (détail /api/v1/pages/<id> → offre ?options=prices) : priceLevels.price_min en cents (taxes+frais inclus) → prix plancher (92,8 % des séances) + statut PAR séance (saleState, séances datées sans heure → repli au jour) ; cache data/ticketpro_cache.json, TP_PRICE_MAX=40/sync, re-visite 3 j ; 8 tenants QC (+arsenalcontemporarysale, +lefifa)",
   "acces_legal": "Billetterie publique ; robots.txt n'interdit que /admin/ /gui/ /report/ (vérifié 2026-08-22) ; API du site officiel consommée telle quelle, GET throttlés 1 s, UA honnête, lien d'achat vers la fiche officielle /fr/pages/<id> du tenant",
   "couverture": "Théâtre St-Denis + Studio St-Denis (Montréal), Fun Nation (Salle Pierre-Mercure, Monument-National, Club Soda), ExpoCité (Québec), Salle André-Gagnon (La Pocatière), Palais des congrès de Montréal, La Belle Église de Chertsey, Théâtre Rialto, Huntingdon… ~200 spectacles / ~1 100 séances datées (vérifié 2026-08-22)",
   "cadence": "horaire (watcher PM2)",
   "statut": "actif"
  },
  {
   "id": "zeffy",
   "name": "Zeffy — billetterie OSBL",
   "url": "https://www.zeffy.com/",
   "type": "billetterie",
   "extraction": "sitemap des organisations (api.zeffy.com/sitemap/organizations/sitemap-0.xml, ~4 400 pages fr-CA/en-CA) → pages org rendues serveur (__NEXT_DATA__ organizationPage.upcomingEvents : dates UTC, adresse, image, URL) filtrées « , QC » et formCategory=Event, puis fiches billetterie JSON-LD offers[].price pour les tarifs réels ; incrémental cache 7 j, plafonds ZEFFY_ORG_MAX=400 / ZEFFY_DETAIL_MAX=80. RÉACTIVÉE 2026-08-25 (le sitemap billets était infaisable ; les pages d'organisations sont la bonne surface)",
   "acces_legal": "robots.txt Disallow: /*=$ uniquement (aucune URL visée) + sitemaps publiés ; GET throttlés, identification honnête, pas d'anti-bot constaté",
   "couverture": "~100-200 événements OSBL QC actifs (galas, spectacles-bénéfice, ateliers communautaires), toutes régions",
   "cadence": "quotidienne",
   "statut": "actif"
  },
  {
   "id": "showpass",
   "name": "Showpass — billetterie canadienne",
   "url": "https://www.showpass.com/",
   "type": "billetterie",
   "extraction": "API JSON publique /api/public/events/ paginée, couverture du Québec par 10 points géo (location__point_location=lat,lng,rayon + starts_on__gte), filtre province=QC côté connecteur ; heure locale via local_starts_on ; tarifs ticket_types[].price. RÉACTIVÉE 2026-08-25 (l'écartement « aucun filtre géo » est invalidé — le paramètre fonctionne)",
   "acces_legal": "robots.txt Allow: /api/ (API publique explicitement autorisée), GET throttlés 0,8 s, identification honnête",
   "couverture": "~30-40 événements QC actifs (soirées, croisières, festivals, Candlelight) — toutes régions balayées",
   "cadence": "quotidienne",
   "statut": "actif"
  },
  {
   "id": "weezevent",
   "name": "Weezevent — billetterie libre-service",
   "url": "https://www.weezevent.com/",
   "type": "billetterie",
   "extraction": "—",
   "acces_legal": "robots.txt permissif mais aucune surface de découverte publique",
   "couverture": "minisites my.weezevent.com avec JSON-LD Event complet, mais non énumérables (sitemap = 28 URLs tournantes France, pas de recherche publique, API par organisateur)",
   "cadence": "—",
   "statut": "abandonnee",
   "note": "ÉCART CONFIRMÉ 2026-08-25 : aucune surface d'énumération publique — tout connecteur dépendrait de l'index Google. Les gros clients QC sont déjà captés par les ATR/agrégateurs."
  },
  {
   "id": "accesculture",
   "name": "Accès culture — réseau culturel de Montréal",
   "url": "https://www.accesculture.com/",
   "type": "agregateur",
   "extraction": "—",
   "acces_legal": "—",
   "couverture": "AUCUNE : domaine recyclé (ferme SEO hôtels) hébergeant une copie fossilisée du site 2015 ; toute date « déduite » serait fabriquée",
   "cadence": "—",
   "statut": "abandonnee",
   "note": "RE-SONDÉE 2026-08-25 : domaine squatté, contenu figé 2015 (dates réelles : mars-mai 2015) — connecteur retiré pour éviter la fabrication de dates. L'offre des maisons de la culture reste couverte par montreal + lavitrine."
  },
  {
   "id": "cotenord",
   "name": "Tourisme Côte-Nord — événements (ATR)",
   "url": "https://www.tourismecote-nord.com/fr/activites/culture-et-decouverte/evenements-et-spectacles/",
   "type": "tourisme-regional",
   "extraction": "JSON embarqué « var fiches » de la page liste (1 GET/sync : titre, description, dates ISO, ville, adresse, GPS, tarif, site web) + fiches détail incrémentales pour l'image (cache, CN_FICHE_MAX=10, re-visite 7 j)",
   "acces_legal": "Pages publiques de l'ATR, robots.txt « Allow: / » — GET throttlés, UA honnête, lien vers la fiche originale",
   "couverture": "Côte-Nord (Manicouagan + Duplessis)",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "abitibi",
   "name": "Tourisme Abitibi-Témiscamingue — festivals et événements (ATR)",
   "url": "https://abitibi-temiscamingue.org/festivals-et-evenements/",
   "type": "tourisme-regional",
   "extraction": "Pages liste SSR (3-4 pages × 12 cartes : titre, plage de dates FR, ville, image Tourinsoft) via auto-escalade anti-bot (Cloudflare challenge → Scrapfly ASP), budget ABT_PAGE_MAX=4 requêtes/sync, aucune fiche détail",
   "acces_legal": "Pages publiques de l'ATR — requêtes throttlées et plafonnées (coût Scrapfly), UA honnête, lien vers la fiche originale",
   "couverture": "Abitibi-Témiscamingue",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "ilesdelamadeleine",
   "name": "Tourisme Îles-de-la-Madeleine — festivals et événements (ATR)",
   "url": "https://www.tourismeilesdelamadeleine.com/fr/decouvrir-les-iles/experiences/culture/festivals-et-evenements/",
   "type": "tourisme-regional",
   "extraction": "Cartes SSR de la liste (titre, dates FR, catégorie, image) + fiches détail incrémentales (microdonnées schema.org : adresse/ville/CP, description, dates ; cache, IDM_FICHE_MAX=10, re-visite 7 j)",
   "acces_legal": "Pages publiques de l'ATR, robots.txt permissif — GET throttlés, UA honnête, lien vers la fiche originale",
   "couverture": "Îles-de-la-Madeleine",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "charlevoix",
   "name": "Tourisme Charlevoix — calendrier des événements (ATR)",
   "url": "https://www.tourisme-charlevoix.com/fr/evenements",
   "type": "tourisme-regional",
   "extraction": "Index Algolia public du site (prod_event_fr, clé search-only embarquée dans le JS) : 1 requête/sync (end>=hier) → titre, description, adresse, GPS, catégories, dates+heures réelles ; enrichissement /api/get-event incrémental (image, site web, prix, gratuité ; cache, CHX_FICHE_MAX=20, re-visite 7 j)",
   "acces_legal": "Clé Algolia « search-only » et API publiées par le site lui-même — requêtes throttlées, UA honnête, lien vers la fiche originale",
   "couverture": "Charlevoix (→ Capitale-Nationale)",
   "cadence": "quotidienne",
   "statut": "actif"
  },
  {
   "id": "eeyouistchee",
   "name": "Eeyou Istchee Baie-James — événements (ATR)",
   "url": "https://www.eeyouistcheebaiejames.com/fr/quoi-faire/evenements/",
   "type": "tourisme-regional",
   "extraction": "Cartes SSR de la liste (titre, ville, plage de dates FR, image) + fiches détail incrémentales (description, code postal, site web ; cache, EIB_FICHE_MAX=10, re-visite 7 j)",
   "acces_legal": "Pages publiques de l'ATR (domaine decrochezcommejamais.com → redirection) — GET throttlés, UA honnête, lien vers la fiche originale",
   "couverture": "Eeyou Istchee Baie-James (→ Nord-du-Québec)",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "tourismelaval",
   "name": "Tourisme Laval — événements (ATR)",
   "url": "https://www.tourismelaval.com/explorer-possibilites/evenements/",
   "type": "tourisme-regional",
   "extraction": "Cartes SSR FacetWP (CPT event, 2 pages : titre, plage de dates FR, catégorie, extrait, image) — REST wp/v2/event verrouillé (401 Kadence) et calendrier tribe mort à la source (déc. 2025)",
   "acces_legal": "Pages publiques de l'ATR — GET throttlés, UA honnête, lien vers la fiche originale",
   "couverture": "Laval",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "quebeccite",
   "name": "Québec cité — calendrier des événements (ATR)",
   "url": "https://www.quebec-cite.com/fr/quoi-faire-quebec/evenements",
   "type": "tourisme-regional",
   "extraction": "Index Algolia public du site (default_fr_event_date_start_asc, clé search-only du thème Drupal) : 1 requête/sync (event_date_end>=hier) → titre, résumé, salle, GPS, prix, gratuité, catégories, image, lien officiel ; dates à 12:00 UTC sur tout l'index = jour entier → aucune heure émise",
   "acces_legal": "Clé Algolia « search-only » publiée par le site lui-même — requêtes throttlées, UA honnête, lien vers la fiche originale",
   "couverture": "Région de Québec (→ Capitale-Nationale)",
   "cadence": "quotidienne",
   "statut": "actif"
  },
  {
   "id": "mtlorg",
   "name": "Tourisme Montréal (mtl.org) — festivals et événements (ATR)",
   "url": "https://www.mtl.org/fr/quoi-faire/festivals-et-evenements",
   "type": "tourisme-regional",
   "extraction": "Index Algolia public du site (prod_fr, facettes _sections:Festivals et événements + content_type:product) : 1 requête/sync → titre, description, plages de dates structurées _open_dates, adresse, GPS, sous-catégories, image CDN ; les fiches sans date (salles/attraits) sont écartées",
   "acces_legal": "Clé Algolia « search-only » publiée par le site lui-même — requêtes throttlées, UA honnête, lien vers la fiche originale",
   "couverture": "Montréal",
   "cadence": "quotidienne",
   "statut": "actif"
  },
  {
   "id": "saguenaylacsaintjean",
   "name": "Tourisme Saguenay–Lac-Saint-Jean (ATR)",
   "url": "https://saguenaylacsaintjean.ca/quoi-faire",
   "type": "tourisme-regional",
   "extraction": "n/d",
   "acces_legal": "n/d",
   "couverture": "Saguenay–Lac-Saint-Jean",
   "cadence": "n/d",
   "statut": "abandonnee",
   "note": "ÉCARTÉE 2026-08-25 (vague ATR) : site TYPO3 = annuaire d'attraits SANS calendrier — aucune date d'événement publiée (fiches festivals = horaires d'ouverture seulement, vérifié live + sitemap). La ville de Saguenay reste couverte par saguenaysorties. À re-sonder si l'ATR publie un agenda."
  },
  {
   "id": "troisrivieres",
   "name": "Ville de Trois-Rivières — Calendrier des activités",
   "url": "https://www.v3r.net/activites-et-loisirs/calendrier-des-activites",
   "type": "municipal",
   "extraction": "endpoint JSON public /ajax/wp-queries/archive-activites.php (POST, 1 requête — celui du composant AngularJS ; wp-json 401 contourné proprement). Remplace la source « trois-rivieres » abandonnée (API WP verrouillée)",
   "acces_legal": "site municipal public, robots.txt permissif, identification honnête",
   "couverture": "Trois-Rivières (Mauricie)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "rimouski",
   "name": "Ville de Rimouski — Événements",
   "url": "https://rimouski.ca/loisirs-culture/activites/evenements",
   "type": "municipal",
   "extraction": "flux RSS étendu du site (1 requête, balises maison startDate/eventTime/location — salle et adresse séparées)",
   "acces_legal": "flux RSS public du site municipal",
   "couverture": "Rimouski (Bas-Saint-Laurent)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "victoriaville",
   "name": "Ville de Victoriaville — Quoi faire à Victo",
   "url": "https://victoriaville.ca/calendriers-cours-et-ateliers/quoi-faire-a-victo",
   "type": "municipal",
   "extraction": "HTML serveur Craft, navigation ?dateDebut par semaine (VIC_WEEKS=4) ; « 00h00 » = placeholder toute-la-journée → heure None",
   "acces_legal": "page municipale publique, robots.txt permissif",
   "couverture": "Victoriaville (Centre-du-Québec)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "drummondville",
   "name": "Ville de Drummondville — Calendrier des événements",
   "url": "https://www.drummondville.ca/culture-loisirs-et-sports/calendrier-des-evenements/",
   "type": "municipal",
   "extraction": "HTML serveur Toolset (?wpv_view_count extrait du formulaire + wpv_paged) + fiches (lieu, coût) en cache incrémental (DRU_FICHES=40)",
   "acces_legal": "site municipal public, robots.txt permissif (wp-admin seulement)",
   "couverture": "Drummondville (Centre-du-Québec)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "granby",
   "name": "Ville de Granby — Calendrier des événements (liste éditoriale)",
   "url": "https://www.granby.ca/fr/calendrier-evenements",
   "type": "municipal",
   "extraction": "HTML serveur (blocs éditoriaux h5 + dates FR + lien externe), parsing tolérant, 1 requête — aucun calendrier structuré à la source (jsonapi désactivé, listing Drupal vide côté serveur)",
   "acces_legal": "site municipal public, robots.txt permissif",
   "couverture": "Granby (Estrie)",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "saintjerome",
   "name": "Ville de Saint-Jérôme — Calendrier",
   "url": "https://www.vsj.ca/calendrier/",
   "type": "municipal",
   "extraction": "HTML serveur FacetWP (?fwp_calendar_dates=<aujourd'hui>&fwp_paged=N, 10 cartes/page) — date, heure, lieu+adresse, description, image",
   "acces_legal": "site municipal public, robots.txt permissif",
   "couverture": "Saint-Jérôme (Laurentides)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "sainthyacinthe",
   "name": "Ville de Saint-Hyacinthe — Calendrier des événements",
   "url": "https://www.st-hyacinthe.ca/loisirs-et-culture/evenement/calendrier-des-evenements",
   "type": "municipal",
   "extraction": "HTML serveur (?ms=2 « tous les mois », 1 requête) + fiches modales /php/load-modal-info.php en cache incrémental (STH_FICHES=60) : lieu, clientèle, organisateur, gratuité",
   "acces_legal": "site municipal public, GET throttlés, identification honnête",
   "couverture": "Saint-Hyacinthe (Montérégie)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "rouynnoranda",
   "name": "Ville de Rouyn-Noranda — Événements",
   "url": "https://www.rouyn-noranda.ca/evenements",
   "type": "municipal",
   "extraction": "HTML serveur OctoberCMS + fiches (heures/lieu) en cache ; dates publiées SANS année → résolution « prochaine occurrence » documentée",
   "acces_legal": "site municipal public, robots.txt permissif",
   "couverture": "Rouyn-Noranda (Abitibi-Témiscamingue)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "shawinigan",
   "name": "Ville de Shawinigan — Calendrier des événements",
   "url": "https://www.shawinigan.ca/loisirs-et-culture/evenements/calendrier/",
   "type": "municipal",
   "extraction": "HTML serveur (plugin tri-evenements, cartes -single et -list, date fiable dans l'URL) + fiches (date de fin, lieu) en cache",
   "acces_legal": "site municipal public, robots.txt permissif",
   "couverture": "Shawinigan (Mauricie)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "joliette",
   "name": "Ville de Joliette — Événements",
   "url": "https://www.joliette.ca/evenements",
   "type": "municipal",
   "extraction": "HTML serveur OctoberCMS/Blanko /evenements/N + fiches (heures, « Gratuit ») en cache",
   "acces_legal": "site municipal public, robots.txt permissif",
   "couverture": "Joliette (Lanaudière)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "magog",
   "name": "Ville de Magog — Événements et activités (agenda Google public)",
   "url": "https://www.ville.magog.qc.ca/calendrier/evenements-et-activites/",
   "type": "municipal",
   "extraction": "flux iCal Google public embarqué par la page municipale (1 232 VEVENT, 1 requête) : conversion UTC/TZID/VALUE=DATE + expansion RRULE DAILY/WEEKLY (COUNT/UNTIL/BYDAY) plafonnée à 365 j",
   "acces_legal": "calendrier Google publié publiquement par la Ville sur sa page",
   "couverture": "Magog (Estrie)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "soreltracy",
   "name": "Ville de Sorel-Tracy — Événements",
   "url": "https://ville.sorel-tracy.qc.ca/evenements",
   "type": "municipal",
   "extraction": "HTML serveur OctoberCMS /evenements/N + fiches (heures, lieu, coût) en cache (SOR_FICHES=40)",
   "acces_legal": "site municipal public, robots.txt permissif",
   "couverture": "Sorel-Tracy (Montérégie)",
   "cadence": "quotidien",
   "statut": "actif"
  },
  {
   "id": "signelaval",
   "name": "Signé Laval — calendrier culturel officiel de Laval",
   "url": "https://signelaval.com/",
   "type": "agregateur",
   "extraction": "sitemap public /sitemap/events/N.xml puis fiches rendues serveur : JSON-LD Event Footlight/artsdata (dates ISO -04:00, lieu, adresse, image IIIF, organisateur ; champs multilingues en liste → variante fr) ; incrémental cache 7 j, plafond SIGNELAVAL_MAX_FETCH",
   "acces_legal": "robots.txt sans Disallow + sitemap public, GET directs throttlés 0,8 s, identification honnête",
   "couverture": "~290 fiches (bibliothèques, spectacles, expositions, plein air — Laval)",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "quoifaire",
   "name": "Quoi faire — agrégateur de sorties québécois",
   "url": "https://quoifaire.com/",
   "type": "agregateur",
   "extraction": "listes HTML rendues serveur /<ville>/evenements (+?page=N, 5 sections villes) puis fiches serveur : dates FR, heure (À confirmer→None), prix publié brut, région touristique, lieu/adresse, lat/lng Google Maps, auditoire, og:image ; incrémental cache 7 j, plafond QUOIFAIRE_DETAIL_MAX=150",
   "acces_legal": "robots.txt Allow: / (seuls /search et admin exclus, non visités), GET throttlés 0,8 s, identification honnête",
   "couverture": "centaines de fiches à venir (Québec, Montréal, Saguenay, Outaouais, Mauricie) — site lent, sections parfois 502 (tolérées)",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "evenementsattractions",
   "name": "Événements Attractions Québec (quebecvacances.com)",
   "url": "https://www.quebecvacances.com/",
   "type": "agregateur",
   "extraction": "sitemap paginé /sitemap.xml?page=1..4 → fiches /fr/evenements/<slug> JSON-LD Event (dates de la prochaine édition, lieu, ville, image Cloudinary) ; anti-bot 403 → chaîne de secours Oxylabs/Scrapfly/Bright Data avec réparation d'encodage UTF-8 ; incrémental cache 14 j, plafond EAQ_DETAIL_MAX=80",
   "acces_legal": "robots.txt User-agent: * / Allow: / ; rate-limiting poli, identification honnête ; coût escalade contenu par cache",
   "couverture": "696 fiches sitemap (festivals/événements membres EAQ, toute la province) — ~1/3 avec dates publiées",
   "cadence": "hebdomadaire",
   "statut": "actif"
  },
  {
   "id": "banq",
   "name": "BAnQ — calendrier des activités",
   "url": "https://www.banq.qc.ca/calendrier/a-venir",
   "type": "agregateur",
   "extraction": "Scrapfly obligatoire (anti-bot Radware) : liste rendue JS → fiches HTML serveur via Scrapfly sans JS, JSON-LD Event complet (dates ISO -04:00, lieu, adresse, image, organisateur, offers.price 0.00 = gratuité publiée) ; incrémental cache 14 j, plafond BANQ_DETAIL_MAX=50",
   "acces_legal": "robots.txt Drupal standard (calendrier non exclu) ; 1 rendu JS + ≤50 fiches par sync, cadence contenue",
   "couverture": "~140 activités à venir (Grande Bibliothèque + centres régionaux — ateliers, conférences, heure du conte)",
   "cadence": "hebdomadaire",
   "statut": "actif"
  }
 ]
}