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>
This commit is contained in:
Allison
2026-04-28 08:57:36 -04:00
parent 64738bfd1f
commit 55569366f4
15 changed files with 1034 additions and 6 deletions

View File

@@ -0,0 +1,27 @@
{% extends 'marketing/base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block description %}{{ description }}{% endblock %}
{% block content %}
<section class="bg-brand-bg py-16 px-4 min-h-[60vh]" aria-labelledby="legal-index-title">
<div class="max-w-3xl mx-auto">
<header class="mb-8 text-center">
<p class="text-xs uppercase tracking-wider text-brand-navy/70 mb-2">DictIA Inc.</p>
<h1 id="legal-index-title" class="text-3xl md:text-4xl font-black text-brand-navy mb-3">Documents légaux</h1>
<p class="text-sm text-brand-navy/70">Version {{ legal_version }} de l'ensemble des documents.</p>
</header>
<ul class="space-y-3" role="list">
{% for page in pages %}
<li>
<a href="{{ url_for('legal.legal_page', page=page.slug) }}" class="block p-5 bg-white border border-brand-border rounded-[12px] hover:border-brand-b1 hover:shadow-cta transition focus-visible:outline-2 focus-visible:outline-brand-b1 focus-visible:outline-offset-2">
<h2 class="text-lg font-semibold text-brand-navy mb-1">{{ page.title }}</h2>
<p class="text-sm text-brand-navy/70">{{ page.description }}</p>
</a>
</li>
{% endfor %}
</ul>
</div>
</section>
{% endblock %}