diff --git a/templates/marketing/landing.html b/templates/marketing/landing.html
index e003bc3..a24a240 100644
--- a/templates/marketing/landing.html
+++ b/templates/marketing/landing.html
@@ -314,16 +314,16 @@
{
'critere': 'Conforme Loi 25 sans transfert hors-Québec',
'dictia': '✓ Hébergement OVH Beauharnois',
- 'teams': '⚠ Soumis Cloud Act (US)',
+ 'teams': '✗ Soumis Cloud Act (US)',
'otter': '✗ Hébergement US',
'whisper': '✓ Aucun transfert (local)'
},
{
- 'critere': 'Exposé au Cloud Act US',
- 'dictia': '✗ Aucune exposition',
- 'teams': '✓ Microsoft = entité US',
- 'otter': '✓ Otter.ai Inc. = US',
- 'whisper': '✗ Local'
+ 'critere': 'Souveraineté hors Cloud Act US',
+ 'dictia': '✓ Aucune exposition',
+ 'teams': '✗ Microsoft = entité US',
+ 'otter': '✗ Otter.ai Inc. = US',
+ 'whisper': '✓ Local'
},
{
'critere': 'WhisperX Large-v3 fine-tuné FR-CA',
@@ -333,14 +333,14 @@
'whisper': '⚠ FR générique de base'
},
{
- 'critere': 'Diarisation 8 + locuteurs (pyannote)',
- 'dictia': '✓ Jusqu\'à 8',
+ 'critere': 'Diarisation jusqu\'à 8 locuteurs (pyannote)',
+ 'dictia': '✓ Inclus par défaut',
'teams': '⚠ Limité ~6 (Premium)',
- 'otter': '✓ Variable',
+ 'otter': '⚠ Variable selon le forfait',
'whisper': '✗ Non incluse'
},
{
- 'critere': 'Coût par utilisateur/mois',
+ 'critere': 'Coût mensuel par utilisateur',
'dictia': '0 $ (forfait fixe)',
'teams': '~14 $ CAD (Premium)',
'otter': '~20 $ US (Business)',
@@ -395,9 +395,9 @@
{% for card in [
{
- 'icon': '🇨🇦',
+ 'icon': '🍁',
'title': 'Hébergement OVH Beauharnois',
- 'desc': 'Centre de données SOC 2 Type II en territoire québécois. Aucune sortie de juridiction sans consentement explicite et tracé.'
+ 'desc': 'Centre de données opéré par OVHcloud Canada en territoire québécois. Conformité documentée selon les services (ISO 27001, SOC 2 selon le périmètre). Détails sur demande.'
},
{
'icon': '⚖️',
diff --git a/tests/test_marketing_landing_template.py b/tests/test_marketing_landing_template.py
index 32aadd1..497e9b5 100644
--- a/tests/test_marketing_landing_template.py
+++ b/tests/test_marketing_landing_template.py
@@ -523,12 +523,12 @@ def test_comparatif_table_has_4_competitors_and_6_criteria():
assert col in body, f"Comparatif missing column: {col}"
# 6 criteria (extract by their distinctive phrasing)
criteria_keywords = [
- 'Conforme Loi', # row 1
- 'Cloud Act', # row 2
- 'Large-v3 fine-tun', # row 3 (escaped or raw)
- 'Diarisation', # row 4
- 'utilisateur/mois', # row 5
- 'Audit trail' # row 6
+ 'Conforme Loi', # row 1
+ 'Souveraineté hors Cloud Act', # row 2 (renamed)
+ 'Large-v3 fine-tun', # row 3
+ 'Diarisation jusqu', # row 4 (renamed)
+ 'mensuel par utilisateur', # row 5 (renamed)
+ 'Audit trail' # row 6
]
for kw in criteria_keywords:
assert kw in body, f"Comparatif missing criterion containing: {kw}"
@@ -573,6 +573,11 @@ def test_conformite_4_pillars():
assert 'Mapp' in body, "Must use 'Mappé' (not 'Certifié')"
# Citation/contact for verification
assert 'info@dictia.ca' in body
+ # SOC 2 claim must be hedged ('selon le périmètre') not absolute
+ assert 'selon le périmètre' in body or 'selon le périmètre' in body, \
+ "SOC 2 claim must be hedged — see code-review I-3"
+ # ISO 27001 reference is OK (verifiable from OVH compliance page)
+ assert 'ISO' in body and '27001' in body, "Reference to ISO 27001 expected"
def test_conformite_uses_wcag_safe_text_on_dark():
@@ -601,3 +606,18 @@ def test_no_unverifiable_competitor_claims():
]
for phrase in forbidden_phrases:
assert phrase not in body, f"Forbidden competitive claim: {phrase}"
+
+
+def test_comparatif_check_marks_consistently_mean_good():
+ """Each ✓ in the table should mark a 'good' outcome for that column.
+ Regression guard against the inverted-Cloud-Act-row bug.
+ Specifically: DictIA cell of every row must contain ✓ (DictIA wins on every criterion).
+ """
+ client = app.test_client()
+ body = client.get('/').data.decode('utf-8')
+ # The 'Souveraineté hors Cloud Act' row must have ✓ for DictIA (after rename)
+ assert 'Souveraineté hors Cloud Act' in body
+ # And must NOT have the legacy inverted form
+ assert 'Exposé au Cloud Act' not in body, "Row 2 must be reworded to positive convention"
+ # Specifically check Teams gets ✗ for the territoriality criterion (was ⚠ before)
+ assert '✗ Soumis Cloud Act' in body, "Teams must show ✗ for non-Loi-25-compliant transfer"