Files
dictia-public/src/legal/routes.py
Allison 55569366f4 feat(legal): B-2.9 6 pages légales (CGU, Loi 25, cookies, remboursement, accessibilité, mentions)
- src/legal/__init__.py: define canonical LEGAL_VERSION='2026-04-27' constant
  (single source of truth — auth.py now imports it as SIGNUP_LEGAL_VERSION).
- src/legal/routes.py: add /legal/<page> + /legal/ index routes; markdown rendered
  from src/legal/content/*.md with toc, tables, fenced_code, attr_list extensions.
- src/legal/content/: 6 French (Québec) markdown documents — DictIA Inc. /
  InnovA AI S.E.N.C. branding, Loi 25-compliant 12-section privacy policy,
  WCAG 2.2 AA accessibility statement, AGPL-3.0 attribution. All marked
  DRAFT v1.0 pending legal review by Allison Rioux.
- templates/legal/_layout.html + index.html: extends marketing/base.html;
  inline .legal-content typographic styles (no CSS rebuild required).
- .gitignore: allow-rule for src/legal/content/*.md so markdown is tracked
  despite the global *.md ignore.
- tests/test_legal_pages.py: 9 tests covering 200 responses, DictIA branding,
  rprp@dictia.ca presence, 12 mandatory Loi 25 sections, public indexability
  (no X-Robots-Tag noindex), shared layout, marketing/base.html extension,
  DRAFT callout, and LEGAL_VERSION/SIGNUP_LEGAL_VERSION equivalence.
- tests/_run_legal_pages_windows.py: manual driver (Windows fcntl stub).
- static/css/marketing.css: regenerated by `npm run build:css` to include
  new utility classes referenced from templates/legal/*.html.

Tests: 9/9 pass. No off-limits files modified beyond the 2-line auth.py
constant move spec'd in B-2.9. No schema changes; markdown==3.5.1 already
pinned in requirements.txt (B-1.1). Pages publicly indexable by design
(Loi 25 transparency).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 08:57:36 -04:00

85 lines
2.7 KiB
Python

"""Legal pages — 6 markdown-rendered pages (B-2.9).
Each page extends templates/legal/_layout.html and is publicly indexable
(see src/app.py:_PUBLIC_INDEXABLE_PREFIXES = ('marketing.', 'legal.')).
"""
from pathlib import Path
import markdown
from flask import abort, render_template
from src.legal import LEGAL_VERSION, legal_bp
CONTENT_DIR = Path(__file__).parent / 'content'
VALID_PAGES = (
'conditions',
'confidentialite',
'cookies',
'remboursement',
'accessibilite',
'mentions',
)
PAGE_TITLES = {
'conditions': "Conditions d'utilisation",
'confidentialite': "Politique de confidentialité (Loi 25)",
'cookies': "Politique de cookies",
'remboursement': "Politique de remboursement",
'accessibilite': "Déclaration d'accessibilité (WCAG 2.2 AA)",
'mentions': "Mentions légales",
}
PAGE_DESCRIPTIONS = {
'conditions': "Conditions d'utilisation du service DictIA — droits, obligations, responsabilités.",
'confidentialite': "Politique de confidentialité conforme à la Loi 25 du Québec — collecte, conservation, droits des utilisateurs.",
'cookies': "Utilisation des cookies et traceurs sur les sites DictIA.",
'remboursement': "Politique de remboursement des abonnements DictIA.",
'accessibilite': "Engagement DictIA en matière d'accessibilité numérique (WCAG 2.2 AA).",
'mentions': "Mentions légales — DictIA Inc. (filiale d'InnovA AI S.E.N.C.).",
}
def _render_markdown(page: str) -> str:
"""Read the markdown file for `page` and return rendered HTML."""
md_path = CONTENT_DIR / f'{page}.md'
if not md_path.exists():
abort(404)
raw = md_path.read_text(encoding='utf-8')
return markdown.markdown(
raw,
extensions=['toc', 'tables', 'fenced_code', 'attr_list'],
output_format='html5',
)
@legal_bp.route('/<page>')
def legal_page(page):
"""Render one of the 6 legal pages by slug."""
if page not in VALID_PAGES:
abort(404)
return render_template(
'legal/_layout.html',
title=PAGE_TITLES[page],
description=PAGE_DESCRIPTIONS[page],
content=_render_markdown(page),
page=page,
legal_version=LEGAL_VERSION,
)
@legal_bp.route('/')
def legal_index():
"""Index page listing all 6 legal pages."""
pages = [
{'slug': slug, 'title': PAGE_TITLES[slug], 'description': PAGE_DESCRIPTIONS[slug]}
for slug in VALID_PAGES
]
return render_template(
'legal/index.html',
title="Documents légaux DictIA",
description="Index des documents légaux DictIA — conditions, confidentialité, cookies, remboursement, accessibilité, mentions.",
pages=pages,
legal_version=LEGAL_VERSION,
)