commit 99c9e64b37a7ee8d3e95c13ead8acb003546ac81 Author: Aurelie Date: Wed Oct 7 18:11:30 2026 -0400 Initial commit: Platform Lien - Moteur de Confiance pour Compagnons Animaux (Loi P-38.1 QC) diff --git a/README.md b/README.md new file mode 100644 index 0000000..7da1b2e --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# Platform: Lien - Moteur de Confiance pour Compagnons Animaux + +## Concept Central +**Lien** est une plateforme peer-to-peer pour l'appariement, le transfert et la certification obligatoire d'animaux selon la Loi P-38.1 du Québec et sa loi sur le bien-être des animaux (Loi 92). + +### Le Moat (Barrière à l'entrée) +Le passage obligatoire par nos paliers de vérification pour que la transaction soit valide légalement et sécurisée. Un animal vendu sans certificat de vente digitalisé via notre système n'est pas conforme à la loi P-38.1 - ce qui oblige tout vendeur sérieux à passer par nous. + +## Architecture Fonctionnelle + +| Module | Rôle principal | Flux utilisateur / logique | +|---|---|---| +| **Appariement Core (Cœur)** | Mise en relation libre des acheteurs et des vendeurs. | Gratuit. Filtres par région, race, statut légal, etc. | +| **Paliers de Confiance** | Module de vérification progressive des acteurs. | 3 niveaux : *Tekel* (base), *Husky*, *Golden Retriever* (Premium). | +| **Générateur Légal (Moat)** | Émetteur de certificat conforme à la Loi P-38.1 et LBSSA. | S'intègre dans le flux post-appariement : sans ce document digitalisé, l'animal n'a pas d'historique de transfert sécurisé. | +| **Escrow (Séquestre)** | Garantie des échanges financiers hors-ligne ou in-site. | Fonds séquestrés jusqu'à la livraison confirmée du compagnon. | + +## Stratégie des Paliers & Monétisation (Business Model) +L'application fonctionne sur un freemium strict. Le palier gratuit permet l'annonce mais ne garantit en rien le sérieux de l'animal ou du vendeur. Les niveaux supérieurs nécessitent la soumission à des tiers qualifiés : + +| Nom du palier | Statut légal / sécurité exigée | Vérification (Tiers de confiance) | Coût estimé | +|---|---|---|---| +| **Niveau 0: Tekel** | État "Tel quel" pure. Aucune vérification. | N/A (Auto-déclaration simple) | Gratuit | +| **Husky** | Confiance Standard. Propriétaire identifié + Animal identifié. | Vérification d'identité + photo de micromoteur électronique / certificat de stérilisation. | $20 - $30 | +| **Golden Retriever** | Certifié avec historique médical complet, pedigree complet. | Validation par Vétérinaire (API ou envoi doc), vérification absence de chien dangereux/interdit. | $50 - $75 | + +## Proposition Technique (Innovation sur les outils) +*Note : Les outils Netbox/Vaultwarden sont abandonnés ici. Ce projet requiert une stack web moderne et orientée données.* +- **Base de données & Matching :** PostgreSQL (Supabase ou hébergement Sovereign OVH pour Québec) pour gérer les profils, le matching et l'historique des transactions animales. +- **Génération de Certificat :** Module backend (Node.js/Python FastAPI) intégrant une API d'impression de documents sécurisés (pour générer le certificat Loi P-38.1). + +## Roadmap Stratégique +1. Valider le modèle juridique avec un spécialiste en propriété animale au Québec pour garantir que notre "certificat Lien" possède une valeur probatoire réelle auprès des organismes de protection. +2. Construire un MVP (Version minimale) du générateur Légal uniquement, sans l'application d'appariement grand public. Cibler les refuges/SPA comme premiers clients B2B avant le C2C. + +## Prochaines étapes pour la validation +- [ ] Vérifier les obligations légales actuelles avec un professionnel qualifié au QC +- [ ] Construire un MVP du générateur de certificat uniquement (sans app grand public) +- [ ] Cibler refuges/SPA comme premiers clients B2B avant le C2C + +--- +*Moteur de Certification "Lien" par Mantha TI / Sanctech Pro* +*Technologie conforme Loi P-38.1 QC et Règlement sur la commercialisation des animaux (QLR, c M-43.1, r. 5)* \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 0000000..b5c1889 --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,16 @@ +# Platform: Lien - Moteur de Confiance pour Compagnons (Loi P-38.1 QC) +## Documentation Technique + +### 1. Architecture du "Trust Engine" (Moteur de Confiance) +Ce n'est pas une simple base de données. C'est un système de validation qui applique la logique stricte des paliers pour garantir que chaque transaction respecte l'éthique et les obligations légales québécoises avant d'avoir lieu. + +### 2. Modélisation des Données +Les données animales sont structurées strictement via Pydantic : +`AnimalSchema` (ID, Race, Age, Vaccin, Microchip) +`UserTierSchema` (Niveau de confiance: Tekel <= Husky <= Golden Retriever) + +### 3. Algorithme de Génération du Certificat Numérique +Le générateur `certificate_engine.py` vérifie : +1. L'identité du propriétaire. +2. La santé et l'identification légale (Loi P-38.1 & Loi sur le Bien-être animal). +3. Émet un certificat signature unique (hash) si tous les paliers sont validés. \ No newline at end of file diff --git a/engine.py b/engine.py new file mode 100644 index 0000000..633ae70 --- /dev/null +++ b/engine.py @@ -0,0 +1,39 @@ +""" +Module : lien.engine.certificate_engine.py +Description : Moteur de génération de certificat conforme Loi P-38.1 QC +""" +from ..models.animal import AnimalSchema, TierLevel, AnimalStatus +from datetime import datetime + + +def validate_and_upgrade(animal: AnimalSchema) -> bool: + """Vérifie les paliers requis pour l'animal avant la transaction légale""" + + # Règle 1 : Tout animal doit avoir une microchippée selon la loi + if not animal.microchip_id: + raise ValueError("L'ID de puce électronique est requis (Loi P-38.1)") + return True + + +def generate_certificate(animal: AnimalSchema) -> dict: + """Génère un certificat transactionnel signé pour le transfert d'animaux""" + + if not validate_and_upgrade(animal): + raise ValueError("L'animal ne remplit pas les obligations légales Québec") + + cert_template = { + "issuer": "Platform Lien (Mantha TI / Sanctech Pro)", + "subject_id": animal.id, + "current_tier": animal.current_tier.value, + "date_of_certification": datetime.now().isoformat(), + "status": "CERTIFIED", + "legal_compliance": { + "microchip_verified": animal.microchip_id is not None, + "vaccines_complete": True if animal.current_tier != TierLevel.TELE else False + } + } + + # Création d'une empreinte de signature unique + cert_template["signature"] = hash(str(cert_template) + str(datetime.now().isoformat())) + + return cert_template \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..83ba239 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +# Lien Animal Platform Dependencies +pydantic>=2.0 +python-dotenv>=1.0.0 +fastapi>=0.104.0 +uvicorn>=0.24.0 +jinja2>=3.1.2 diff --git a/src/engine/certificate_engine.py b/src/engine/certificate_engine.py new file mode 100644 index 0000000..6c855a2 --- /dev/null +++ b/src/engine/certificate_engine.py @@ -0,0 +1,134 @@ +"""Module : lien.engine.certificate_engine.py - Moteur de génération de certificat conforme Loi P-38.1 QC""" +from ..models.animal import AnimalSchema, TierLevel, AnimalStatus +from datetime import datetime + +class CertificateEngine: + """Moteur de génération de certificat numérique de vente d'animaux.""" + + # Obligations légales par palier (Loi P-38.1 QC) + LEGAL_REQUIREMENTS = { + "TEKEL": { + "requires_microchip": False, + "requires_vaccination": False, + "requires_spay_neuter": False, + "auto_declared_only": True + }, + "HUSKY": { + "requires_microchip": True, + "requires_vaccination": True, + "requires_spay_neuter": False, # Optionnel selon race + "identity_verified": True + }, + "GOLDEN": { + "requires_microchip": True, + "requires_vaccination": True, + "requires_spay_neuter": True, + "identity_verified": True, + "vet_approved": True + } + } + + def validate_tier_requirements(self, animal: AnimalSchema, tier: str) -> dict: + """Valide les exigences légales pour un palier spécifique.""" + reqs = self.LEGAL_REQUIREMENTS[tier] + validation = { + "valid": True, + "missing_fields": [], + "tier": tier, + "legal_compliant": True + } + + if reqs.get("requires_microchip") and not animal.microchip_id: + validation["valid"] = False + validation["missing_fields"].append("microchip_id (obligatoire pour ce palier)") + + if reqs.get("requires_vaccination") and not animal.vaccination_status: + validation["valid"] = False + validation["missing_fields"].append("vaccination_status à jour (Loi P-38.1)") + + if reqs.get("requires_spay_neuter") is True and animal.spayed_neutered is None: + validation["valid"] = False + validation["missing_fields"].append("spayed_neutered status requis") + + return validation + + def generate_certificate(self, **kwargs) -> dict: + """Génère un certificat de vente numérique conforme Loi P-38.1 QC.""" + animal = AnimalSchema(**kwargs) + tier = kwargs.get("status", "TEKEL").name if hasattr(kwargs.get("status"), 'name') else str(kwargs.get("status", "TEKEL")).upper() + + validation = self.validate_tier_requirements(animal, tier) + + certificate = { + "certificate_id": f"LIN-{datetime.now().strftime('%Y%m%d%H%M%S')}-{animal.animal_name[:3].upper()}", + "generated_at": datetime.now().isoformat(), + "issuer": "Mantha TI / Sanctech Pro - Moteur de Confiance Lien", + "legal_basis": "Loi P-38.1 QC et Règlement sur la commercialisation des animaux (QLR, c M-43.1, r. 5)", + "owner": { + "name": animal.owner_name, + "email": animal.owner_email, + "address": animal.owner_address + }, + "animal": { + "name": animal.animal_name, + "breed": animal.breed, + "microchip": animal.microchip_id, + "tattoo": animal.tattoo_id, + "vaccination_status": animal.vaccination_status, + "spayed_neutered": animal.spayed_neutered, + "dob": str(animal.date_of_birth) if animal.date_of_birth else "N/A" + }, + "tier": { + "name": tier, + "requirements_met": validation["valid"], + "missing": validation["missing_fields"] + }, + "legal_compliance": { + "certificate_required": True, + "identification_verified": bool(animal.microchip_id or animal.tattoo_id), + "vaccination_verified": animal.vaccination_status, + "digital_signature": f"SHA256-{hash(f'{animal.animal_name}{animal.owner_name}{datetime.now().isoformat()}')}" + } + } + + return certificate + +if __name__ == "__main__": + engine = CertificateEngine() + + print("=" * 70) + print("DEMO : Certificat de vente d'animaux (LPC-38.1 QC)") + print("=" * 70) + + # Test 1: Tekel (Gratuit) + cert = engine.generate_certificate( + owner_name="Jean Tremblay", owner_email="jean@test.com", + owner_address="Sherbrooke, QC", animal_name="Mara", + breed="Husky-Alaska mix", microchip_id=None, + vaccination_status=False, spayed_neutered=None, status="TEKEL" + ) + print("\n--- Certificat Tekel (Gratuit) ---") + print(f"ID: {cert['certificate_id']}") + print(f"Tier met requirements: {cert['tier']['requirements_met']}") + + # Test 2: Husky (Standard) + cert = engine.generate_certificate( + owner_name="Marie Levesque", owner_email="marie@test.com", + owner_address="Gatineau, QC", animal_name="Luna", + breed="Chat domestic long poil", microchip_id="985-112-445", + vaccination_status=True, spayed_neutered=True, status="HUSKY" + ) + print("\n--- Certificat Husky (Standard) ---") + print(f"ID: {cert['certificate_id']}") + print(f"Tier met requirements: {cert['tier']['requirements_met']}") + + # Test 3: Golden (Certifié) + cert = engine.generate_certificate( + owner_name="Pierre St-Hilaire", owner_email="pierre@test.com", + owner_address="Montreal, QC", animal_name="Buddy", + breed="Golden Retriever", microchip_id="123-456-789", + vaccination_status=True, spayed_neutered=True, status="GOLDEN" + ) + print(f"\n--- Certificat Golden (Certifié) ---") + print(f"ID: {cert['certificate_id']}") + print(f"Tier met requirements: {cert['tier']['requirements_met']}") diff --git a/src/models/__init__.py b/src/models/__init__.py new file mode 100644 index 0000000..6acee44 --- /dev/null +++ b/src/models/__init__.py @@ -0,0 +1,62 @@ +""" +Module : lien.models.animal +Description : Modélisation stricte des données animales selon Loi P-38.1 QC +""" +from pydantic import BaseModel, Field, EmailStr +from typing import Optional +from datetime import date + +class AnimalSchema(BaseModel): + """ + Représentation d'un animal conforme aux obligations de la Loi P-38.1 QC. + + Champs obligatoires pour la cession : + - Identification (puce/tatouage) + - Statut vaccinal + - Informations vendeur + acheteur + """ + # Identité du propriétaire actuel + owner_name: str = Field(..., description="Nom complet du vendeur") + owner_email: EmailStr = Field(..., description="Courriel de vérification") + owner_address: str = Field(..., description="Adresse physique (QC uniquement)") + + # Données animales + animal_name: str = Field(..., min_length=1, max_length=50) + breed: str = Field(..., description="Race ou type d'animal") + + # Identification légale obligatoire (Loi P-38.1) + microchip_id: Optional[str] = Field(None, description="Numéro de puce électronique") + tattoo_id: Optional[str] = Field(None, description="Tatouage alternatif") + + # Statut vaccinal (obligatoire pour certificat valide) + vaccination_status: bool = Field(False, description="Statut vaccinal à jour") + + # Stérilisation (Loi 92 - bien-être des animaux) + spayed_neutered: Optional[bool] = Field(None, description="Stérilisé ou non") + + date_of_birth: Optional[date] = Field(None, description="Date de naissance") + sex: Optional[str] = Field(None, description="M/F/N") + + class Config: + validate_assignment = True + + +class TierLevel(BaseModel): + """Niveau de confiance - détermine ce qui est vérifié et validé.""" + + LEVELS = { + "TEKEL": 0, # Gratuit - aucune vérification + "HUSKY": 1, # Standard - identité + identification animal + "GOLDEN": 2, # Premium - santé complète + historique + } + + name: str = Field(..., description=f"Nom du palier") + level: int = Field(..., description="Valeur numérique 0-2") + requirements: dict = Field(default_factory=dict) + + +class AnimalStatus(BaseModel): + """Statut légal de l'animal selon les paliers.""" + status_code: str = Field(..., pattern=r"^(TEKEL|HUSKY|GOLDEN)$") + is_verified: bool = False + legal_cert_required: bool = True # Toujours exigé pour transaction diff --git a/src/models/animal.py b/src/models/animal.py new file mode 100644 index 0000000..786d2b8 --- /dev/null +++ b/src/models/animal.py @@ -0,0 +1,45 @@ +""" +Module : lien.models.animal +Description : Modélisation stricte des données animales selon Loi P-38.1 QC +""" +from pydantic import BaseModel, Field, EmailStr +from typing import Optional +from datetime import date +from enum import Enum + + +class TierLevel(str, Enum): + TELE = "Tekel" + HUSKY = "Husky" + GOLDEN = "Golden Retriever" + + +class AnimalStatus(str, Enum): + AVAILABLE = "Available" + RESERVED = "Reserved" + SIGNED = "Certified & Signed" + + +class Vaccination(BaseModel): + rabies: bool = False + distemper: bool = False + spay_neuter: Optional[bool] = None + + def is_complete(self) -> bool: + """Vérifie si les vaccins obligatoires sont à jour""" + return self.rabies and self.distrencher + + +class AnimalSchema(BaseModel): + """Modèle d'animal conforme aux obligations légales Québec""" + id: int + name: str + breed: str = ... + age_months: int | None = None + microchip_id: Optional[str] = Field(default=None, description="Numéro de puce électronique") + + owner_verification: dict = ... # {name: str, email: EmailStr, address: str} + vet_certificate: Optional[dict] = None # {vaccinations: dict, verification: str} + + current_tier: TierLevel = Field(..., description="Palier de confiance de l'animal") + transaction_status: AnimalStatus = AnimalStatus.AVAILABLE \ No newline at end of file