Files
singular-particular-space/ToolsnToys/Meshagora/DEPLOY.md
JL Kruger 5422131782 Initial commit — Singular Particular Space v1
Homepage (site/index.html): integration-v14 promoted, Writings section
integrated with 33 pieces clustered by type (stories/essays/miscellany),
Writings welcome lightbox, content frame at 98% opacity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 12:09:22 +02:00

289 lines
11 KiB
Markdown

# Meshagora — Deployment & Troubleshooting
---
## Version History
### v0.2 — IP Detection & Startup Transparency
- Replaced UDP routing trick with `ifconfig` parsing for hotspot IP detection. The UDP trick failed on the Samsung A25 (and likely other Android builds) because the hotspot interface routing entry may not exist at startup. `ifconfig` reads interface addresses directly via socket ioctls — no netlink, no root, no routing assumptions.
- Startup banner now lists all detected non-loopback IPs with interface names, so if the primary guess is wrong the alternatives are immediately visible.
- Added `install_termux.sh` — one-shot setup script for Termux.
- Added `net-tools` as an explicit dependency (`ifconfig` provider).
### v0.1 — Initial prototype
- Single-file Flask app, in-memory SQLite, runs on Android/Termux hotspot.
---
## Dependencies
### Termux (Android) — required packages
| Package | Source | Purpose |
|---------|--------|---------|
| `python` | `pkg` | Runtime |
| `net-tools` | `pkg` | `ifconfig` — hotspot IP detection |
| `libjpeg-turbo` | `pkg` | JPEG support for Pillow (required by `qrcode[pil]`) |
| `libpng` | `pkg` | PNG support for Pillow (required by `qrcode[pil]`) |
| `flask` | `pip` | Web framework |
| `qrcode[pil]` | `pip` | QR code generation at `/qr` |
### Desktop (testing only)
| Package | Source | Purpose |
|---------|--------|---------|
| `flask` | `pip` | Web framework |
| `qrcode[pil]` | `pip` | QR code generation |
`ifconfig` is standard on desktop Linux/macOS — no extra install needed.
---
## Quick Start (Termux)
**First time only — install dependencies:**
```
bash install_termux.sh
```
Or manually:
```
pkg install python net-tools libjpeg-turbo libpng
pip install flask "qrcode[pil]"
```
**Every session:**
1. Enable Android mobile hotspot.
2. Open Termux and run:
```
python3 meshagora.py
```
3. Read the startup banner — note all three keys and the Join URL.
4. Open `http://[IP]:5000/qr` on the server device and display it for participants to scan.
5. Once everyone has joined, go to `/admin` → HIDE QR.
---
## Starting the Server
1. **Enable the Android mobile hotspot before running the script.**
IP detection reads active interfaces at startup — if the hotspot is off, the banner URL will be wrong.
2. Run:
```
python3 meshagora.py
```
3. The startup banner prints:
```
==================================================
MESHAGORA v2.3 — SOCIAL SANDBOX
Admin Post Key : [4 emoji]
Trusted Post Key : [2 emoji]
Default Post Key : [2 emoji]
--------------------------------------------------
Join URL : http://192.168.43.1:5000/join (wlan0)
Also try : http://10.0.2.5:5000/join (rmnet0)
QR code : http://192.168.43.1:5000/qr
If no URL works, run: ifconfig | grep inet
==================================================
```
Write down or photograph all three keys. They cannot be recovered without restarting the server (which destroys the session).
**Reading the banner:**
- "Join URL" is the best-guess hotspot address (`192.168.x.x` preferred).
- "Also try" lines show other detected interfaces. The `rmnet` / `10.x.x.x` entries are mobile data — participants on the hotspot WiFi cannot reach those.
- Samsung A25 hotspot is typically `192.168.43.1` on `wlan0`.
4. Navigate to `http://[IP]:5000/qr` on the server device and display the QR code for participants to scan.
5. Once all participants have joined, hide the QR code from the Admin Panel (`/admin` → HIDE QR).
---
## Connecting Participants
Participants need to:
1. Join the hotspot WiFi (name set by the server device's hotspot settings).
2. Open a browser and scan the QR code, or type the Join URL from the banner.
3. Go to `/join` — choose a username, Profile Key (2 emoji), and Friend Key (2 emoji).
No app install required. Works on any browser from Android 7.0+, iOS Safari, desktop Chrome/Firefox.
---
## Admin Panel
Navigate to `/admin` from any browser connected to the hotspot.
Enter the 4-emoji Admin Post Key when prompted. Authentication persists for that browser session.
**Actions available:**
- Restrict / Unrestrict / Promote / Demote individual users
- View the current Default Post Key (large, readable — copy to board or announce verbally)
- Rotate Default Key manually
- Trigger Flood Attack (creates 5 bot accounts with posts)
- Show / Hide the join QR code
- View raw database tables (users, posts, votes, reports, keys)
- **WHAT THE PLATFORM SEES** — surveillance dashboard (scroll to bottom of admin panel):
- *Deanonymization table*: maps every session label (Anon #N) to real username, tier, post count, and net score
- *Social graph*: all handshake pairs with CONFIRMED / PENDING status
- *Behavioral correlations*: who voted for whom and who reported whom, cross-referenced with confirmed friendships — project mid-session for maximum pedagogical impact
---
## Stopping the Server
`Ctrl+C` in the Termux terminal. The in-memory database is destroyed immediately.
There is no persistent storage — every session starts clean.
---
## Troubleshooting
### Server prints `127.0.0.1` instead of the hotspot IP
**Important:** `127.0.0.1` is the loopback address — it only works in the browser on the server device itself. Participants on other devices will get "connection refused". Flask is still listening on all interfaces (`0.0.0.0`), so the server is reachable — you just need the correct IP.
**Step 1:** Enable the mobile hotspot *before* running `python3 meshagora.py`, then restart. The hotspot interface only appears after the hotspot is on.
**Step 2:** If still wrong, check all interfaces manually:
```
ifconfig | grep inet
```
Look for an address like `192.168.43.1` under `wlan0` — that's the hotspot gateway. Ignore `127.0.0.1` (loopback) and `10.x.x.x` under `rmnet` (mobile data).
Note: `ip addr` fails in Termux with "cannot bind netlink socket: permission denied" — always use `ifconfig` instead.
**Step 3:** Navigate to `http://[correct-ip]:5000/join` directly and distribute that URL to participants.
**Samsung A-series:** The A25 hotspot is typically `192.168.43.1` on `wlan0`. If the banner's "Join URL" shows a different address, check the "Also try" lines for the `192.168.43.1` entry.
---
### `ModuleNotFoundError: No module named 'qrcode'`
```
pip install "qrcode[pil]"
```
If it installs but the error persists:
```
python3 -m pip install "qrcode[pil]"
```
The server runs without qrcode — `/qr` returns a 404. Participants can type the join URL directly.
---
### `ModuleNotFoundError: No module named 'flask'`
```
pip install flask
```
---
### `ifconfig` command not found
```
pkg install net-tools
```
This is required for hotspot IP detection in Termux. Without it, the banner will fall back to `127.0.0.1`.
---
### Port 5000 already in use
Common on macOS (AirPlay Receiver uses 5000).
**Option A:** Kill the other process:
```
lsof -i :5000
kill [PID]
```
**Option B:** Change the port at the bottom of `meshagora.py`:
```python
app.run(host='0.0.0.0', port=5001, debug=False, threaded=False)
```
Update the join URL accordingly.
---
### Participants can't reach the server
1. Confirm participants are connected to the *hotspot WiFi*, not their mobile data or a different network.
2. Confirm the IP in the banner matches `ifconfig | grep inet` output for the `wlan0` interface.
3. Confirm port 5000 is not blocked by a firewall. On Termux this is rarely an issue on a local hotspot.
4. Try navigating to the URL from the server device's own browser first to confirm the server is responding.
---
### Android kills the server mid-session (Termux background kill)
Android aggressively kills background processes to save battery.
**Prevention:**
- In Android Settings → Apps → Termux → Battery → set to "Unrestricted" (wording varies by device).
- Keep Termux in the foreground with the screen on, or acquire a wakelock:
```
termux-wake-lock
```
(Requires the Termux:API app from F-Droid.)
- Keep the server device plugged in to power.
If the server is killed, all session data is lost. Restart with `python3 meshagora.py` — all keys rotate, all users must rejoin.
---
### Default Post Key stopped working for everyone
A user was restricted (by admin action or by 51% community reports). The Default Post Key rotates silently on every restriction. Check the Admin Panel for the new key and distribute it.
---
### Emoji picker doesn't appear / looks broken
The emoji picker is rendered as inline HTML buttons with basic CSS. No JavaScript framework required.
- If buttons appear but emoji don't render: the device font doesn't support those codepoints. This is rare on Android 7.0+ but possible on stripped-down browsers. Participants can type emoji directly into the visible input field.
- If the grid looks misaligned: the scroll container (`max-height: 160px; overflow-y: auto`) is intentional. Scroll within the picker to see all emoji.
---
### Post fails with "Post key incorrect." for a RESTRICTED user
RESTRICTED users require an admin co-sign. The admin must communicate the Admin Post Key directly to the restricted user for them to post. This is by design — it represents supervised posting access.
---
### Handshake says "One or both keys are incorrect."
- Both participants must submit from their own accounts (you cannot complete both sides from one account).
- Emoji must match exactly — the picker submits codepoints, not descriptions.
- Try clearing both fields and reselecting. The CLEAR button resets the hidden input.
- Verify both participants have submitted independently.
---
## Testing Checklist (Pre-Session)
- [ ] Hotspot enabled before starting server — correct IP appears in banner
- [ ] `/qr` loads a scannable QR code from the server device
- [ ] Join as User 1 from a phone — "Anon #1" assigned, Default Post Key shown on join confirmation
- [ ] Join as User 2 from a second device or incognito tab — "Anon #2" assigned
- [ ] Post from User 1 with correct Default Post Key — appears in feed
- [ ] Post from User 1 with wrong key — "Post key incorrect." error
- [ ] Vote from User 2 — score updates
- [ ] Report from User 2 — spoiler overlay appears, User 1 sees notification banner
- [ ] Admin panel accessible at `/admin` with 4-emoji Admin Post Key
- [ ] Admin restricts User 1 — Default Post Key rotates (new key visible in admin panel)
- [ ] User 1 post fails with old key, succeeds with new key (or admin co-sign)
- [ ] Handshake between User 1 and User 2 — confirmed, username appears on posts for the friend
- [ ] Friends-only toggle shows only friend posts
- [ ] Profile notes edit blocked without Profile Key, succeeds with correct key
- [ ] Hide QR via admin → `/qr` returns 404
- [ ] Flood Attack → 5 bot posts appear in feed
- [ ] Scroll to "WHAT THE PLATFORM SEES" in admin panel — all three panels render (deanonymization, social graph, behavioral correlations)
- [ ] Confirm panels are empty (no crash) on a fresh session with no posts/votes/reports