Cause racine (#25) : use_tls=True (défaut) activait le direct TLS sur le port 5222 (conventionnellement STARTTLS). Le client envoyait un ClientHello TLS sur un port attendant un stream XMPP en clair, le serveur ne voyait jamais l'identité configurée, et la session expirait après 30 s. Corrections : - Remplacer use_tls (bool) par tls_mode: Literal[direct|starttls|disabled] (défaut starttls, compatible port 5222). use_tls conservé comme alias déprécié avec DeprecationWarning. - Ajouter connect_timeout (15 s) et cleanup_timeout (10 s) distincts du timeout de session (30 s). - Gérer l'événement connection_failed de Slixmpp pour échouer rapidement au lieu d'attendre le timeout de session. - Borner await connect_future et await disconnect_future par leurs timeouts respectifs (anti-blocage). - Attendre connect_future et session_future conjointement (asyncio.wait, FIRST_COMPLETED) pour détecter connection_failed avant l'expiration du connect_timeout. - Annuler les tâches pending sur tous les chemins de retour, y compris CancelledError et Exception. - Redact tous les redact_exception avec extra_secrets=_secret_values(). - Construire ClientXMPP dans le try (contrat « never raises »). - Enrichir FakeClientXMPP avec modes connect/disconnect configurables. - 25 nouveaux tests (timeout connexion, connection_failed, cleanup bloqué, CancelledError, TLS mismatch, fuite secrets). Couverture 96 %. - Mettre à jour .env.example, GUIDE_DEV_PYTHON.md, README.LLM.md. Co-authored-by: OpenCode <opencode@antoineve.me>
149 lines
4.6 KiB
Markdown
149 lines
4.6 KiB
Markdown
# pronote-sync — AI Agent Setup Guide
|
|
|
|
This document guides an AI agent through installing and pre-configuring the `pronote-sync` project on a fresh Linux host (Debian/CentOS). It covers environment setup, dependency installation, and configuration file preparation. It does **NOT** cover secrets provisioning — those must be provided by the operator.
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- Python ≥ 3.13.5 (check with `python3 --version`)
|
|
- Git
|
|
- A non-root service user (e.g., `pronote-sync`)
|
|
- Target paths:
|
|
- `/opt/pronote-sync` (code)
|
|
- `/var/lib/pronote-sync` (state)
|
|
- `/var/log/pronote-sync` (logs)
|
|
- `/etc/pronote-sync` (config)
|
|
|
|
---
|
|
|
|
## Installation Steps
|
|
|
|
```bash
|
|
# Create service user
|
|
sudo useradd --system --no-create-home --shell /usr/sbin/nologin pronote-sync
|
|
|
|
# Clone the repository
|
|
sudo git clone <repo-url> /opt/pronote-sync
|
|
sudo chown -R pronote-sync:pronote-sync /opt/pronote-sync
|
|
|
|
# Create virtual environment
|
|
cd /opt/pronote-sync
|
|
sudo -u pronote-sync python3.13 -m venv .venv
|
|
sudo -u pronote-sync .venv/bin/pip install -e ".[dev]"
|
|
|
|
# Create directories
|
|
sudo install -d -m 0700 -o pronote-sync -g pronote-sync /etc/pronote-sync
|
|
sudo install -d -m 0750 -o pronote-sync -g pronote-sync /var/lib/pronote-sync
|
|
sudo install -d -m 0750 -o pronote-sync -g pronote-sync /var/log/pronote-sync
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration Preparation (Without Secrets)
|
|
|
|
```bash
|
|
# Copy the example config
|
|
sudo -u pronote-sync cp /opt/pronote-sync/.env.example /etc/pronote-sync/pronote-sync.env
|
|
|
|
# The operator must fill in secrets (PRONOTE_PASSWORD, CALDAV_PASSWORD, XMPP_PASSWORD, AI_API_KEY, etc.)
|
|
# Do NOT populate secrets automatically — leave them for the operator.
|
|
```
|
|
|
|
### Non-Secret Environment Variables (Pre-Configurable)
|
|
|
|
The following variables can be safely pre-configured in `/etc/pronote-sync/pronote-sync.env`:
|
|
|
|
- **Pronote:**
|
|
- `PRONOTE_ACCOUNT_TYPE` (default: `parent`)
|
|
- `PRONOTE_ENT` (ENT slug, e.g., `lyceeconnecte`)
|
|
- `PRONOTE_AGENDA_SOURCE`, `PRONOTE_HOMEWORK_SOURCE`, `PRONOTE_MESSAGES_SOURCE` (`auto`, `ical`, or `pronotepy`)
|
|
|
|
- **CalDAV:**
|
|
- `CALDAV_CALENDAR_PATH` (e.g., `/pronote-sync/`)
|
|
- `CALDAV_ALLOW_INSECURE_HTTP` (default: `false`)
|
|
|
|
- **Sync Window:**
|
|
- `SYNC_PAST_DAYS`, `SYNC_FUTURE_DAYS`
|
|
|
|
- **Theoretical Agenda:**
|
|
- `THEORETICAL_AGENDA_PATH`, `SCHOOL_HOLIDAYS_PATH`
|
|
- `THEORETICAL_WEEK_ANCHOR_DATE`, `THEORETICAL_WEEK_ANCHOR_TYPE`
|
|
|
|
- **XMPP:**
|
|
- `XMPP_ENABLED`, `XMPP_HOST`, `XMPP_PORT`, `XMPP_TLS_MODE`, `XMPP_TIMEOUT`, `XMPP_CONNECT_TIMEOUT`, `XMPP_CLEANUP_TIMEOUT`, `XMPP_RESOURCE`
|
|
- `XMPP_USE_TLS` is deprecated but still supported (aliased to `XMPP_TLS_MODE`)
|
|
|
|
- **AI:**
|
|
- `AI_ENABLED`, `AI_PROVIDER`, `AI_BASE_URL`, `AI_MODEL`, `AI_ALLOW_INSECURE_HTTP`
|
|
|
|
- **Blog:**
|
|
- `BLOG_ENABLED`, `BLOG_RSS_URL`
|
|
|
|
- **General:**
|
|
- `DRY_RUN`, `LOG_LEVEL`
|
|
|
|
### Secret Variables (Operator Must Provide)
|
|
|
|
**Do NOT set these variables automatically.** The operator must manually provide the following secrets:
|
|
|
|
- **Pronote:**
|
|
- `PRONOTE_ICAL_URL`, `PRONOTE_URL`, `PRONOTE_USERNAME`, `PRONOTE_PASSWORD`
|
|
|
|
- **CalDAV:**
|
|
- `CALDAV_URL`, `CALDAV_USERNAME`, `CALDAV_PASSWORD`
|
|
|
|
- **XMPP:**
|
|
- `XMPP_JID`, `XMPP_PASSWORD`, `XMPP_TO`
|
|
|
|
- **AI:**
|
|
- `AI_API_KEY`
|
|
|
|
---
|
|
|
|
## Pre-Deployment Checks
|
|
|
|
```bash
|
|
# Verify no secrets in the codebase
|
|
/opt/pronote-sync/.venv/bin/python /opt/pronote-sync/scripts/check_secrets.py
|
|
|
|
# Verify dependencies
|
|
/opt/pronote-sync/.venv/bin/python -m pip check
|
|
|
|
# Dry-run test (will fail without secrets, but verifies the environment)
|
|
/opt/pronote-sync/.venv/bin/pronote-sync --dry-run
|
|
```
|
|
|
|
---
|
|
|
|
## systemd Installation
|
|
|
|
```bash
|
|
# Install systemd units
|
|
sudo install -m 0644 /opt/pronote-sync/deploy/systemd/pronote-sync.service /etc/systemd/system/
|
|
sudo install -m 0644 /opt/pronote-sync/deploy/systemd/pronote-sync.timer /etc/systemd/system/
|
|
|
|
# Install logrotate config
|
|
sudo install -m 0644 /opt/pronote-sync/deploy/logrotate/pronote_sync /etc/logrotate.d/pronote_sync
|
|
|
|
# Reload and enable
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now pronote-sync.timer
|
|
```
|
|
|
|
---
|
|
|
|
## Notes for the AI Agent
|
|
|
|
- **Do NOT commit or write secrets** to any file in the repository.
|
|
- **Do NOT modify** `.gitignore`, `pyproject.toml`, or existing source files.
|
|
- If `python3.13` is not available, install it first:
|
|
- Debian: `sudo apt install python3.13`
|
|
- CentOS: Compile from source or use `dnf` if available.
|
|
- The `check_secrets.py` script exits with:
|
|
- `0` (clean)
|
|
- `1` (secrets found)
|
|
- `2` (error)
|
|
- All paths in the systemd unit assume `/opt/pronote-sync` — adjust if installed elsewhere.
|
|
- The operator **must** provide real values for all **SECRET** variables before enabling the timer.
|