Anciennement CoproApp, renommée Proprietas en septembre 2026 (nouvelle identité visuelle ; le dépôt GitHub devient
LostInTheBugs/Proprietas, les anciennes URLs redirigent). Version courante : 2026.09.016.
Gestion de copropriété pour syndic bénévole, conçue pour le régime « petite copropriété » français (art. 41-8 de la loi du 10 juillet 1965, issu de l'ordonnance n° 2019-1101 : ≤ 5 lots à usage de logements, bureaux ou commerces, ou budget prévisionnel moyen < 15 000 €/an) et utilisable sans limite de lots — 12 lots, 15 lots ou plus : comptabilité simplifiée, consultation écrite, majorités de vote automatiques.
https://proprietas.cloudfr.net (anciennement https://copro.cloudfr.net, conservé) — un compte de démonstration est préconfiguré avec deux copropriétés complètes (Paris : 5 lots, comptes 2024-2026, AG + PV, documents, plan pluriannuel de travaux ; Lyon : 3 lots) :
| Champ | Valeur |
|---|---|
demo@proprietas.cloudfr.net |
|
| Mot de passe | demo123456 |
Un second compte illustre la vue « copropriétaire » (consultation) : Marie Dubois
possède le lot 1 des Tilleuls et le déclare « propriétaire occupant » (Réglages →
Mes lots), et modifie ses coordonnées (Réglages → Mes informations). Tous les
propriétaires de la démo ont un compte (mot de passe demo123456) : marie.dubois@,
jean.martin@, sophie.bernard@, paul.petit@, contact.sci-lilas@,
karim.benali@, claire.fontaine@, enzo.rossi@ (tous en @example.com).
| Champ | Valeur |
|---|---|
marie.dubois@example.com |
|
| Mot de passe | demo123456 |
Le compte démo ne bloque pas l'inscription : le premier compte réel peut toujours se créer normalement depuis la page de connexion.
- Immeuble & lots : lots, tantièmes (millièmes), propriétaires (des comptes utilisateurs — « zéro fiche »), occupation des lots (« propriétaire occupant », « loué » ou « vacant » — déclarée lot par lot par son propriétaire dans Réglages → Mes lots ; aucun nom de locataire enregistré, RGPD)
- Comptabilité simplifiée : budget prévisionnel, appels de fonds automatiques par tantièmes, encaissements / dépenses, solde par lot, état daté, quittances
- Fonds de travaux : taux configurable (min. légal 5 %), suivi dédié
- Recouvrement des impayés : décompte détaillé par provision (imputation FIFO, échu / à échoir), relances email, mise en demeure générée (PDF), suivi du délai de 30 jours, article 19-2 (exigibilité immédiate des provisions), intérêts au taux légal, frais, étapes amiables et judiciaires
- Assemblées générales : convocations, résolutions, moteur de majorités légal (art. 24 / 25 / 26, unanimité, régime 2 copropriétaires), procès-verbaux
- Consultation écrite (régime petite copropriété, unanimité)
- Documents : contrats, devis, factures, diagnostics (stockage local)
- Contacts : annuaire des entreprises, fournisseurs et artisans (téléphone, email, adresse, site web), recherche, catégories
- Contrats : énergie (EDF…), assurance copro, entretien — montant, période, renouvellement automatique, fournisseur lié, échéances suivies automatiquement (alertes J-60, badges Expiré / Expire bientôt, tri par urgence)
- Carnet d'entretien : interventions, prestataires, coûts
- Exports : registre des copropriétés, compte de gestion annuel
- Multi-copropriétés : un compte, plusieurs immeubles isolés, vue consolidée
- Comptes utilisateurs : les propriétaires sont des comptes (prénom, nom, email, téléphone, adresse, rôle, mot de passe) ; chacun modifie ses propres coordonnées (Réglages → Mes informations) et déclare l'occupation de ses lots (Mes lots) ; suppression confirmée et tracée, historique conservé (relances / convocations / actes)
- Rôle copropriétaire (consultation) : les jetons d'écriture (copropriété, fonds de travaux, emails, relances, comptes utilisateurs, recouvrement, sécurité) sont refusés par l'API ; les écrans correspondants sont masqués — le copropriétaire consulte la situation, les assemblées et les documents, et gère ses propres informations
- Trésorerie visible par tous : le compte bancaire séparé du syndicat et le compte dédié du fonds de travaux s'affichent en lecture seule aux copropriétaires (Réglages → Trésorerie de la copropriété), avec les montants portés au crédit selon la comptabilité (encaissements − dépenses) — seule la modification reste au syndic
- Sécurité : double authentification TOTP (compatible FreeOTP, Aegis, Google Authenticator…), codes de secours, réinitialisation assistée par le syndic, journal d'audit, alertes email de connexion
- Thème clair / sombre : au choix par compte (Réglages → Apparence) — clair, sombre ou système (suit l'appareil), appliqué dès le chargement sans clignotement
- Multi-pays : module de règles par pays (France en V1, extensible)
- Backend : FastAPI + SQLAlchemy + JWT (Python 3.11)
- Frontend : React + TypeScript + Vite + Tailwind
- Base de données : PostgreSQL (prod) / SQLite (dev)
- Déploiement : Docker Compose + Caddy (TLS auto) — hébergé sur un serveur dédié, derrière Cloudflare
# Backend (port 8000)
cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
alembic upgrade head # crée/met à jour le schéma (SQLite dev)
uvicorn app.main:app --reload --port 8000
# Frontend (port 5173)
cd frontend
npm install
npm run devPremier lancement : créer le compte syndic via POST /api/auth/register (ouvert tant qu'aucun utilisateur n'existe).
COPRO_SECRET_KEYobligatoire hors dev : le backend refuse de démarrer (hors base SQLite) si la clé de signature JWT n'a pas été définie — la valeur par défautchange-meest publique et permettrait de forger des tokens. Génération :python -c "import secrets; print(secrets.token_hex(32))".- Rate limiting sur
/api/auth/login: 5 tentatives échouées par email et par IP sur 15 minutes, puis429(limiteur en mémoire, adapté à une instance mono-serveur). - Session par cookie
HttpOnly: le jeton de session n'est pas accessible au JavaScript (rien danslocalStorage), posé à la connexion —SameSite=Lax,Securederrière HTTPS, supprimé au logout. Le headerBeareret?token=restent acceptés pour l'API/CLI (scripts, tests) ; les jetons hérités des versions précédentes sont migrés automatiquement en cookie au premier chargement (aucune reconnexion nécessaire). - Upload de documents : plafond configurable
COPRO_UPLOAD_MAX_MB(défaut 25 Mo,413au-delà) et liste blanche d'extensions (.pdf .jpg .jpeg .png .doc .docx .xls .xlsx .odt .ods,400sinon). - CORS : liste d'origines configurable
COPRO_CORS_ORIGINS(JSON). Vide en production — le frontend est servi par le même backend. En dev (SQLite),http://localhost:5173est autorisé automatiquement. - Isolation multi-copropriétés : tout accès par identifiant est scopé à la copropriété active du token (404 si l'objet appartient à une autre copro).
- Double authentification (TOTP, RFC 6238) : par compte, sans dépendance
externe — compatible avec toute application d'authentification (FreeOTP, Aegis,
Google Authenticator…). Codes de secours à usage unique (affichés une seule fois),
désactivation protégée par mot de passe + code, réinitialisation assistée par le
syndic (tracée). Politique par copropriété :
off|syndic|all— les nouvelles copropriétés reçoiventCOPRO_TOTP_DEFAULT_POLICY(défautsyndic; l'app desktop la force àoff). Le secret TOTP est chiffré en base (clé dérivée deCOPRO_SECRET_KEY: changer cette clé impose aux comptes de ré-enrôler leur 2FA). Les jetons intermédiaires (vérification du code, enrôlement forcé) sont à portée limitée et courts (10 / 30 min) ; les tentatives 2FA partagent le rate-limit du login. - Journal d'audit : connexions (succès et échecs), activation / désactivation / réinitialisation 2FA, usage des codes de secours, création, modification et suppression de comptes, exports (compte de gestion, quittances, rapport annuel, CSV, registre) et envois de relances — consultable par le syndic (page « 🔐 Sécurité ») pour la copropriété active.
- Alertes email de sécurité (best effort, via le SMTP de la copropriété) : connexion depuis une nouvelle IP, 2FA désactivée ou réinitialisée, code de secours utilisé.
Page « 💶 Recouvrement » (réservée au syndic) : par lot, un dossier suit la procédure légale — relances email → mise en demeure → article 19-2 → amiable → contentieux.
- Décompte détaillé : imputation FIFO des encaissements sur les appels les plus anciens ; distinction échu / à échoir. La mise en demeure liste la nature et le montant de chaque provision échue impayée (exigence de précision — cf. Cass. 3e civ., 18 juin 2026, n° 24-19.950).
- Mise en demeure (PDF) : générée depuis le dossier (mentions du compte Service-Public F2603 : identité et adresse du copropriétaire, décompte, délai de 30 jours, conséquences). L'app trace le mode d'envoi et la référence (lettre recommandée électronique — la voie électronique est la règle, le papier l'exception — ou remise). L'envoi recommandé électronique se fait chez un prestataire externe (type AR24) : l'app prépare le courrier, le syndic l'envoie.
- Article 19-2 : 30 jours après la mise en demeure restée infructueuse, l'app calcule les provisions non encore échues de l'exercice + les restes des exercices précédents devenus immédiatement exigibles (activation assistée, tracée, jamais automatique).
- Intérêts et frais : taux de l'intérêt légal paramétrable (arrêté semestriel, saisi par le syndic — pas de taux inventé par l'app), intérêts courus estimés depuis la mise en demeure, frais de recouvrement imputés au dossier (à la charge du débiteur).
- Étapes suivantes : conciliation / commissaire de justice / saisine du tribunal (≤ 5 000 € : règlement amiable obligatoire avant le juge, conciliateur gratuit ; le syndic n'a pas besoin d'autorisation d'AG pour le recouvrement ; prescription 5 ans).
cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt -r requirements-dev.txt
python -m pytest -q # 139 tests, ~70 % de couverture (pytest --cov)La suite (pytest + TestClient, SQLite en mémoire) couvre : isolation multi-copro,
majorités légales (art. 24/25/26, unanimité, régime 2 copropriétaires, passerelle
25-1), tantièmes et appels de fonds (total ≠ 1000, arrondis au centime), soldes
par lot, authentification (register fermé, login, switch-copro, expiration),
double authentification (enrôlement, connexion en deux étapes, codes de secours à
usage unique, politiques par copropriété, réinitialisation par le syndic), journal
d'audit (droits, isolation inter-copro, pagination), fonds de travaux 5 %,
recouvrement (décompte FIFO et imputation, statuts du dossier, mise en demeure
générée, article 19-2, permissions syndic), thème utilisateur (défaut, mise à
jour, validation, NULL lisible), sessions (cookie HttpOnly, priorité d'auth,
migration, logout), génération PDF (non vide + régression
du compte de gestion) et un flux complet de bout en bout. CI : .github/workflows/ci.yml (push + PR).
L'ancien test_e2e.py (script urllib contre une instance réelle) vit désormais
dans backend/scripts/smoke_e2e.py : conservé comme smoke test manuel d'un
déploiement réel, le parcours équivalent tournant en CI dans test_flux_complet.py.
Des versions autonomes (aucun serveur, aucun Docker) sont produites par la CI
(desktop/) et jointes à chaque release GitHub :
Proprietas-Windows.zip— double-clic surProprietas.exe; données dans le dossierdata/à côté de l'exécutable ;Proprietas-macOS.zip— double-clic surProprietas.app(Apple Silicon ; premier lancement : clic droit → Ouvrir) ; données dansdata/à côté de l'application (repli :~/Library/Application Support/Proprietassi l'emplacement est en lecture seule).
Les deux archives incluent le guide utilisateur en FR / EN / DE / LU. Téléchargement : dernière release.
Production : https://proprietas.cloudfr.net + legacy https://copro.cloudfr.net (Cloudflare proxy → serveur de production, Caddy TLS Let's Encrypt).
- Réseau local (défaut) :
docker compose up -d→ l'application écoute sur le port 8000, accessible depuis votre réseau (aucun domaine requis). - Accès depuis internet :
COPRO_DOMAIN="copro.exemple.fr" docker compose --profile internet up -d --build→ ajoute le proxy TLS (Caddy, certificats Let's Encrypt automatiques). Plusieurs domaines possibles, séparés par des virgules (COPRO_DOMAIN="copro.fr, ancien.fr").
Dans l'application, le profil est affiché et VÉRIFIÉ : 🔐 Sécurité → « Accès depuis internet » (réservé au syndic) — déclarez où vit l'application, renseignez l'URL publique puis lancez le diagnostic (HTTPS, certificat, DNS, en-têtes, rate-limit, couverture 2FA). La première requête vue depuis internet est détectée automatiquement : un bandeau propose l'assistant — une exposition ne peut pas passer inaperçue.
Depuis une connexion personnelle, préférez un tunnel à l'ouverture de ports :
- Cloudflare Tunnel :
cloudflared tunnel --url http://localhost:8000(essai) ; en production, un tunnel nommé vers votre domaine (Cloudflare Zero Trust, gratuit jusqu'à 50 utilisateurs) ; - ou Tailscale Funnel.
Activez ensuite le durcissement dans 🔐 Sécurité → « Accès depuis internet » et vérifiez avec le diagnostic.
Le schéma est géré par Alembic (backend/alembic/, URL lue depuis COPRO_DATABASE_URL —
aucune duplication dans alembic.ini). Les migrations tournent explicitement, jamais au
démarrage de l'application : le CMD du conteneur backend exécute alembic upgrade head puis
lance uvicorn (idempotent ; un seul conteneur backend dans le compose actuel).
-
Installation neuve (nouveau serveur / base vide) : rien à faire, le conteneur migre seul.
-
Base existante créée par l'ancien
create_all+_MIGRATIONS(cas de l'instance actuelle) : bascule unique à faire avant de laisser démarrer le nouveau conteneur, pour marquer le schéma existant comme déjà migré sans le rejouer :cd /opt/copro-app git pull sudo docker compose build sudo docker compose run --rm backend sh -c "alembic stamp head" # base existante : marquer, ne pas rejouer sudo docker compose up -d # démarre : upgrade head = no-op + uvicorn
Vérification :
sudo docker compose exec backend alembic currentdoit afficherhead. -
Évolutions futures :
alembic revision --autogenerate -m "..."(backend/), relire la migration, commit, puis le déploiement l'applique au démarrage.
# Sur le serveur de production (utilisateur avec droits docker)
cd /opt/copro-app
git pull
sudo docker compose up -d --build # réseau local
sudo docker compose --profile internet up -d --build # instance exposée (proxy TLS)Le build multi-stage (Dockerfile racine backend/Dockerfile) compile le frontend (Node 20)
et construit le backend (Python 3.11) : plus aucune manipulation manuelle du bundle —
le conteneur sert le dist/ produit au build. Le frontend est inclus dans l'image.
.env(racine) :POSTGRES_PASSWORD+COPRO_SECRET_KEY(jamais commités)- Attention : pas de
dockersans sudo pour l'utilisateur du serveur → toujourssudo docker compose … - Caddy redémarre automatiquement en cas d'échec de certificat (retry 60 s)
