| .codex | ||
| .mcp/problems | ||
| .serena | ||
| ai-validation | ||
| android | ||
| config | ||
| deploy | ||
| docs | ||
| runtime-validation | ||
| src | ||
| test | ||
| .dockerignore | ||
| .gitignore | ||
| AGENTS.md | ||
| Dockerfile | ||
| package.json | ||
| pnpm-lock.yaml | ||
| README.md | ||
| tsconfig.json | ||
Pix Drop
Pix Drop est un service local minimal pour envoyer des photos, vidéos ou documents depuis un téléphone vers un dossier choisi de l’infra maison.
Flux cible :
Galerie Android → Partager → Pix Drop → destination → upload LAN/VPN → /srv/photos-drop/...
État actuel
Ce dépôt contient maintenant :
- serveur HTTP Node/TypeScript ;
- authentification par token d’appareil ;
- rôles admin et
destinationManager; - destinations configurées côté serveur et modifiables via API admin ;
- endpoint raw streamable pour uploader un fichier sans charger tout le fichier en mémoire ;
- staging puis déplacement atomique vers le dossier final ;
- cleanup staging après succès, doublon ou upload interrompu ;
- manifest JSON par import ;
- browse/download HTTP avec ranges ;
- miniatures serveur via
sharppour images etffmpegpour vidéos ; - client Android natif partage/upload/galerie ;
- enregistrement de liens partagés avec retour rapide à l’app source, routage par fournisseur et Direct Share ;
- projection catalogue SQLite reconstructible avec canonicalisation, déduplication des liens et miniature YouTube ; l’état métier durable
library_*n’est pas reconstructible depuis les seuls fichiers ; - métadonnées riches Open Graph/Twitter des liens web génériques, avec fetch borné et protection SSRF ;
- recherche FTS5 unifiée sur le catalogue historique et les éléments natifs actifs, filtrée par destinations et memberships d’espace, avec emplacement courant, lifecycle trash/restore, reconstruction idempotente et portée globale ou espace courant dans la Bibliothèque Android ;
- identité Android observable et persistée comme cache présentatif scoped au serveur, avec rafraîchissement au démarrage/foreground, états hors ligne/refus/incompatibilité, distinction LAN-VPN des routes sensibles et hub Gérer gardé par les capacités confirmées ;
- shell Android Régie réversible avec Bibliothèque, Recherche et Transferts comme destinations visibles, Compte secondaire, aliases historiques, entrée Bibliothèque revalidée et indicateurs issus de la projection canonique ;
- domaine durable Profils/Espaces/Memberships avec backup SQLite et rapport de parité ;
- éléments stables, dossiers hiérarchiques, stockage natif opaque et APIs Espaces/Dossiers/Éléments, avec compatibilité des destinations historiques ;
- navigation Android Espaces/Dossiers, fil d’Ariane, cible
À classeret upload natif parfolderId, avec repli sur les anciennes destinations ; - albums natifs comme collections ordonnées au sein d’un espace, sans déplacement des éléments, avec consultation et création depuis Android ;
- déplacements logiques intra-espace des éléments et dossiers, unitaires ou multiples, avec audit, conservation des collections, anti-cycle et sélecteur hiérarchique Android ;
- déplacements inter-espaces natifs personnel/partagé avec prévisualisation anti-périmée, contrôle des droits source/cible, retrait atomique des collections source, conservation du stockage opaque et confirmation Android ;
- upload résumable par sessions persistantes et chunks offsetés, avec idempotence, vérification SHA-256, reprise Android des gros fichiers et long-running Worker foreground partageant le même moteur que le service immédiat ;
- mode voyage Android avec envoi immédiat, attente d’un réseau non facturé ou conservation manuelle, plafond mobile configurable et projection canonique queue/WorkManager/service/réseau partagée par Accueil, Transferts, Envoi, Sauvegardes, badge et notifications ;
- sauvegarde montante Android depuis MediaStore ou un dossier SAF choisi, avec inventaire local durable, backlog auto-alimenté, progression globale indépendante des jobs de 15, lease d’exécution avec heartbeat, notification unifiée, pause/reprise de toute la règle, galerie locale compacte centrée sur les médias, miniatures, ouverture, recherche, tris, filtres et badges d’état, diagnostic des erreurs et reprise ciblée ou globale, ainsi qu’un nettoyage sûr des imports de test vers la corbeille ; MP-02 apporte désormais la garantie serveur durable après recréation de règle, réinstallation ou changement d’appareil, avec reconnaissance limitée au même profil, au même dossier cible et au même SHA-256, provenances multi-device et imports manuels distincts ;
- Corbeille Android plein écran, visuelle et paginée, avec ouverture des médias supprimés, multisélection, sélection de tous les éléments, restauration par lot, suppression définitive par lots idempotents et progression déterminée X/N jusqu’à la fin du vidage d’un espace ;
- titres logiques éditables pour les éléments natifs et historiques, avec titre source conservé, audit, recherche mise à jour et persistance après reconstruction du catalogue, sans renommer les fichiers physiques ;
- mise à la Corbeille atomique d’une sélection explicite importante ou de tous les éléments directs d’un dossier, avec exclusions, snapshot anti-périmé, limite de 20 000 éléments et aucune récursion ;
- preview non destructive du cycle de vie d’un dossier, distinguant portée directe et récursive future, volumes, collections, éléments déjà trashés, protection système et sauvegardes Android locales concernées, sans aucune mutation récursive ;
- tests d’intégration HTTP sur auth, admin, upload, reprise après coupure, browse, ranges, thumbnails, liens, recherche et domaine Bibliothèque, plus tests de rollback inter-espace et tests Android des politiques de reprise, voyage et synchronisation.
Installation
pnpm install
pnpm run build
Configuration
Copier l’exemple :
cp config/pix-drop.example.json config/pix-drop.local.json
Générer un hash de token :
node -e "const {createHash}=require('node:crypto'); const t=process.argv[1]; console.log('sha256:'+createHash('sha256').update(t).digest('hex'))" 'mon-token-long'
Démarrage
PIX_DROP_CONFIG=config/pix-drop.local.json pnpm start
Par défaut, le serveur écoute sur 0.0.0.0:1338.
API MVP
Santé :
curl http://localhost:1338/api/health
Destinations et identité de l'appareil reconnu :
curl -H "Authorization: Bearer <token>" http://localhost:1338/api/destinations
curl -H "Authorization: Bearer <token>" http://localhost:1338/api/me
Administration : /admin est protegee par authentification HTTP Basic avec le token admin comme mot de passe. L'API /api/admin/destinations permet de creer ou modifier un album avec le token destinationManager ou le token admin complet.
Cycle de vie des appareils :
curl -H "Authorization: Bearer <admin-token>" http://localhost:1338/api/admin/devices
curl -X POST -H "Authorization: Bearer <admin-token>" http://localhost:1338/api/admin/devices/pascal-s10/disable
curl -X POST -H "Authorization: Bearer <admin-token>" http://localhost:1338/api/admin/devices/pascal-s10/enable
curl -X POST -H "Authorization: Bearer <admin-token>" http://localhost:1338/api/admin/devices/pascal-s10/rotate-token
La rotation renvoie un nouveau token clair une seule fois. L'ancien token devient invalide immédiatement. Les appareils désactivés sont refusés à l'authentification.
Limites operationnelles configurables :
limits.maxAdminJsonBodyByteslimite les payloads JSON admin ;limits.maxConcurrentUploadslimite le nombre d'uploads actifs ;limits.uploadTimeoutMscoupe les uploads trop longs ;rateLimits.auth,rateLimits.adminetrateLimits.uploadappliquent des fenetres fixes par IP client.
Upload raw d’un fichier :
curl \
-X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: image/jpeg" \
--data-binary @photo.jpg \
"http://localhost:1338/api/upload/raw?destinationId=a-trier&filename=photo.jpg"
Le client Android pourra appeler cet endpoint une fois par fichier partagé, ce qui évite de devoir parser du multipart côté serveur au MVP.
Validation
pnpm run typecheck
pnpm run build
pnpm test
pnpm run android:check
pnpm run android:check exécute les tests Android et assembleDebug. Il répare un JAVA_HOME invalide, réutilise un JDK 17+ déjà disponible et, si nécessaire, initialise une seule fois un JDK 21 vérifié dans android/.toolchains/.
Documentation
Index courant : docs/INDEX.md.
Documents principaux : docs/API.md, docs/CONCEPTION.md, docs/RUNBOOK_DEPLOYMENT.md, docs/HARDENING_LOTS.md, docs/LOT8_ADMIN_WEB_ANDROID.md.
Exploitation
Le runbook complet est dans docs/RUNBOOK_DEPLOYMENT.md.
Doctor local/proxy :
node dist/src/deployment-doctor.js config/pix-drop.local.json '<token-device>' --url http://127.0.0.1:1338