Fix MQTT topic pattern for OwnTracks and implement privacy isolation

CRITICAL FIX: The OwnTracks app publishes to owntracks/<username>/<device_id>,
not owntracks/owntrack/<device_id>. This was causing data delivery failures
and privacy violations.

Changes:
- Fix ACL topic pattern: owntracks/<username>/# (was: owntracks/owntrack/<device_id>)
- Backend now uses MQTT_ADMIN_USERNAME for global subscription
- Update UI forms and placeholders with correct pattern
- Update email template with correct topic format
- Enable Mosquitto ACL file for user isolation
- Add migration script for existing ACL rules
- Update documentation (README, GEMINI.md)

Privacy & Security:
- Each user isolated at MQTT broker level via ACL
- Backend subscribes with admin credentials to owntracks/+/+
- Web UI filters data by parent_user_id for additional security
- GDPR compliant multi-layer defense in depth

Files changed:
- lib/mqtt-db.ts - Updated createDefaultRule() to use username
- app/api/mqtt/credentials/route.ts - Pass username to ACL creation
- app/admin/mqtt/page.tsx - UI forms and state management
- emails/mqtt-credentials.tsx - Email template topic pattern
- lib/mqtt-subscriber.ts - Use admin credentials from env
- mosquitto/config/mosquitto.conf - Enable ACL enforcement
- README.md, GEMINI.md - Documentation updates
- scripts/fix-acl-topic-patterns.js - Migration script
- MQTT_TOPIC_FIX.md - Detailed implementation guide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 21:49:31 +00:00
parent e78d961f11
commit 31c0e1f572
10 changed files with 340 additions and 19 deletions

View File

@@ -81,9 +81,9 @@ The most straightforward way to run the application and its dependent MQTT broke
The application follows a clean, decoupled architecture.
**Data Ingestion Flow:**
1. An OwnTracks client publishes a location update to a specific MQTT topic (e.g., `owntracks/user/device10`).
1. An OwnTracks client publishes a location update to a specific MQTT topic (e.g., `owntracks/device_12_4397af93/12` where `device_12_4397af93` is the MQTT username).
2. The Mosquitto broker receives the message.
3. The Next.js application's MQTT Subscriber (`lib/mqtt-subscriber.ts`), which is started on server boot via `instrumentation.ts`, is subscribed to the `owntracks/+/+` topic.
3. The Next.js application's MQTT Subscriber (`lib/mqtt-subscriber.ts`), which is started on server boot via `instrumentation.ts`, is subscribed to the `owntracks/+/+` topic with admin credentials.
4. Upon receiving a message, the subscriber parses the payload, transforms it into the application's `Location` format, and saves it to `data/locations.sqlite` using the functions in `lib/db.ts`.
**Data Retrieval Flow:**