Upload
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Klangkiste Dev Playbook
|
||||
|
||||
## Purpose
|
||||
This playbook documents the "virtual box" development environment. It is a complete, hardware-free simulation that runs entirely inside the repo and lets you test setup, playback, and API flows end-to-end.
|
||||
|
||||
Docs live in the repo-level `docs/` to keep all dev guidance in one predictable place for both Box and GUI contributors.
|
||||
|
||||
## Prerequisites
|
||||
- Python 3
|
||||
- Node.js + npm
|
||||
- From repo root
|
||||
|
||||
## Step-by-step
|
||||
Quickstart (3-5 minutes):
|
||||
1) Start everything:
|
||||
```
|
||||
./dev.sh
|
||||
```
|
||||
2) Open the WiFi setup UI:
|
||||
```
|
||||
http://127.0.0.1:9000/setup
|
||||
```
|
||||
3) Add a WiFi profile and submit.
|
||||
4) Check status:
|
||||
```
|
||||
curl http://127.0.0.1:8000/status
|
||||
```
|
||||
5) Start playback:
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"nfc_on","payload":{"uid":"UID_1"}}'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
- Box not starting:
|
||||
- Ensure dependencies are installed and ports 8000/9000 are free.
|
||||
- GUI cannot reach API:
|
||||
- Check `VITE_BOX_API_URL` and Box logs.
|
||||
|
||||
## What Is Mock vs Real
|
||||
- Mock: WiFi, IP, Spotify, audio, hardware. These are logical simulations only.
|
||||
- Real: Box process, playback state machine, API, CLI, resume logic, media traversal.
|
||||
|
||||
## Link Index
|
||||
- Dev workflow: `docs/dev-workflow.md`
|
||||
- Box lifecycle: `docs/box-lifecycle.md`
|
||||
- Setup WebGUI: `docs/setup-webgui.md`
|
||||
- HTTP API contract: `docs/api.md`
|
||||
- GUI control panel: `docs/gui-control-panel.md`
|
||||
- Playback testing: `docs/playback-testing.md`
|
||||
- Offline scenarios: `docs/offline-scenarios.md`
|
||||
- Security & storage: `docs/security-storage.md`
|
||||
- CLI reference: `docs/cli.md`
|
||||
- Virtual box notes: `docs/virtual-box.md`
|
||||
- Legacy storage notes: `docs/storage.md`
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
# Box HTTP API
|
||||
|
||||
## Purpose
|
||||
Defines the stable contract between the GUI/CLI and the Box.
|
||||
The Box is authoritative; the client only sends commands and reads status.
|
||||
|
||||
## Prerequisites
|
||||
- Box running on `http://127.0.0.1:8000`
|
||||
|
||||
## Step-by-step
|
||||
### Status
|
||||
```
|
||||
curl http://127.0.0.1:8000/status
|
||||
```
|
||||
|
||||
### Command (example)
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"nfc_on","payload":{"uid":"UID_1"}}'
|
||||
```
|
||||
|
||||
## GET /status
|
||||
Response fields:
|
||||
- `box_id`: unique device ID
|
||||
- `wifi_state`: `WIFI_UNCONFIGURED | WIFI_CONNECTING | WIFI_ONLINE | WIFI_OFFLINE`
|
||||
- `ip_address`: simulated IP (`192.168.4.1` or `127.0.0.1`)
|
||||
- `connected_ssid`: connected SSID or `null`
|
||||
- `wifi_profiles_count`: number of stored profiles
|
||||
- `spotify_status`: `NOT_CONFIGURED | READY`
|
||||
- `playback_state`:
|
||||
- `state`: `IDLE | PLAYING | PAUSED`
|
||||
- `active_uid`
|
||||
- `playback_root`
|
||||
- `current_file`
|
||||
- `file_index`
|
||||
- `position`
|
||||
- `duration`
|
||||
- `volume`
|
||||
- `last_error`
|
||||
|
||||
Example response:
|
||||
```
|
||||
{
|
||||
"box_id": "klangkiste-a9f3k7m2q8",
|
||||
"wifi_state": "WIFI_ONLINE",
|
||||
"ip_address": "127.0.0.1",
|
||||
"connected_ssid": "HomeWiFi",
|
||||
"wifi_profiles_count": 1,
|
||||
"spotify_status": "READY",
|
||||
"playback_state": {
|
||||
"state": "PLAYING",
|
||||
"active_uid": "UID_1",
|
||||
"playback_root": "media/book_1",
|
||||
"current_file": "/root/klangkiste/box/data/media/book_1/01.mp3",
|
||||
"file_index": 0,
|
||||
"position": 42,
|
||||
"duration": 180,
|
||||
"volume": 40,
|
||||
"last_error": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## POST /command
|
||||
Request body:
|
||||
```
|
||||
{
|
||||
"command": "nfc_on",
|
||||
"payload": { "uid": "UID_1" }
|
||||
}
|
||||
```
|
||||
|
||||
Supported commands:
|
||||
- `nfc_on` `{ uid }`
|
||||
- `nfc_off` `{ uid }`
|
||||
- `play_pause`
|
||||
- `next`
|
||||
- `prev`
|
||||
- `volume_up`
|
||||
- `volume_down`
|
||||
- `vol_up` (alias)
|
||||
- `vol_down` (alias)
|
||||
- `stop`
|
||||
- `trigger_error` `{ type }`
|
||||
- `wifi_add_profile` `{ ssid, password, priority? }`
|
||||
- `wifi_reset`
|
||||
- `spotify_set_tokens` `{ access_token, refresh_token, expires_at, account_id? }`
|
||||
- `spotify_clear`
|
||||
|
||||
Example: add WiFi profile
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"wifi_add_profile","payload":{"ssid":"HomeWiFi","password":"secret","priority":10}}'
|
||||
```
|
||||
|
||||
Example: set Spotify tokens
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"spotify_set_tokens","payload":{"access_token":"a","refresh_token":"b","expires_at":123}}'
|
||||
```
|
||||
|
||||
## Checklist
|
||||
- ✅ `GET /status` returns JSON
|
||||
- ✅ `POST /command` returns `{ "ok": true }`
|
||||
- ✅ No secrets appear in `/status`
|
||||
|
||||
## Troubleshooting
|
||||
- 400 responses:
|
||||
- Check required fields in the payload.
|
||||
- CORS errors:
|
||||
- Ensure Box API is running on the expected host/port.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Box Lifecycle
|
||||
|
||||
## Purpose
|
||||
Defines the virtual box lifecycle: identity, WiFi states, and restart behavior.
|
||||
|
||||
## Prerequisites
|
||||
- Box started with `python3 box/main.py run`
|
||||
|
||||
## Step-by-step
|
||||
### Box identity
|
||||
- Generated on first start if `box/data/box.json` has no `box_id`.
|
||||
- Format: `klangkiste-<10 chars a-z0-9>`
|
||||
- Stored in `box/data/box.json`
|
||||
|
||||
### WiFi states (logical)
|
||||
- `WIFI_UNCONFIGURED`: no profiles stored
|
||||
- `WIFI_CONNECTING`: reserved for future; not emitted in mock
|
||||
- `WIFI_ONLINE`: profile exists and mock is "connected"
|
||||
- `WIFI_OFFLINE`: profile exists but not connected
|
||||
|
||||
### IP model (informational)
|
||||
- Setup/AP mode: `192.168.4.1`
|
||||
- Normal mode: `127.0.0.1`
|
||||
|
||||
### Restart behavior
|
||||
- Box reloads `box_id`, resume state, and WiFi profiles from `box/data/`
|
||||
- Playback resume and WiFi status are preserved
|
||||
|
||||
### Resets
|
||||
- WiFi reset: clears WiFi profiles only (`wifi_reset` command)
|
||||
- Factory reset: delete `box/data/box.json`, `box/data/state.json`, `box/data/secrets.enc`
|
||||
|
||||
## Checklist
|
||||
- ✅ After first boot, `box/data/box.json` contains `box_id`
|
||||
- ✅ `GET /status` returns `wifi_state` and `ip_address`
|
||||
- ✅ WiFi reset clears profiles, `wifi_state=WIFI_UNCONFIGURED`
|
||||
|
||||
## Troubleshooting
|
||||
- `wifi_state` not changing:
|
||||
- Add a WiFi profile via setup UI or API.
|
||||
- Missing `box_id`:
|
||||
- Ensure `box/data/box.json` is writable.
|
||||
+39
-29
@@ -1,45 +1,55 @@
|
||||
# Klangkiste Box CLI
|
||||
# Box CLI Reference
|
||||
|
||||
This document lists all currently available CLI interactions (Phase 1a).
|
||||
## Purpose
|
||||
List all CLI interactions available in the virtual box.
|
||||
|
||||
## Commands
|
||||
## Prerequisites
|
||||
- Box code available in `box/`
|
||||
|
||||
### status
|
||||
Show the current runtime status.
|
||||
|
||||
Example:
|
||||
## Step-by-step
|
||||
### One-shot commands
|
||||
Status:
|
||||
```
|
||||
python box/main.py status
|
||||
python3 box/main.py status
|
||||
```
|
||||
|
||||
### simulate-nfc <uid>
|
||||
Simulate NFC tag detection. Resolves the UID to a playback object from `box/config/box_config.json` and starts playback.
|
||||
|
||||
Example:
|
||||
Simulate NFC:
|
||||
```
|
||||
python box/main.py simulate-nfc CHIP_1
|
||||
python3 box/main.py simulate-nfc UID_1
|
||||
python3 box/main.py simulate-nfc-off UID_1
|
||||
```
|
||||
|
||||
### simulate-nfc-off <uid>
|
||||
Simulate NFC tag removal. Stops playback and stores progress for that UID.
|
||||
|
||||
Example:
|
||||
Manual tick:
|
||||
```
|
||||
python box/main.py simulate-nfc-off CHIP_1
|
||||
python3 box/main.py tick 30
|
||||
```
|
||||
|
||||
### tick <seconds>
|
||||
Simulate playback time progression. Advances position and moves to next file when a file ends.
|
||||
|
||||
Example:
|
||||
### Interactive run mode
|
||||
```
|
||||
python box/main.py tick 90
|
||||
python3 box/main.py run
|
||||
```
|
||||
Commands inside run mode:
|
||||
```
|
||||
status
|
||||
nfc <UID>
|
||||
nfc-off <UID>
|
||||
tick <seconds>
|
||||
play | pause
|
||||
next | vor
|
||||
prev | zurueck
|
||||
vol-up | lauter
|
||||
vol-down | leiser
|
||||
help
|
||||
exit | quit
|
||||
```
|
||||
|
||||
### run
|
||||
Start an interactive session that keeps state in memory. Use `help` inside the session for available commands.
|
||||
## Checklist
|
||||
- ✅ `status` prints runtime state
|
||||
- ✅ `simulate-nfc` starts playback
|
||||
- ✅ `run` accepts interactive commands
|
||||
|
||||
Example:
|
||||
```
|
||||
python box/main.py run
|
||||
```
|
||||
## Troubleshooting
|
||||
- Commands not found:
|
||||
- Ensure you run from repo root or use full path to `box/main.py`.
|
||||
- No playback:
|
||||
- Check tags in `box/data/box.json` and media under `box/data/media`.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Dev Workflow
|
||||
|
||||
## Purpose
|
||||
How to start/stop the virtual box, how to access logs, and how to point the GUI to the API.
|
||||
|
||||
## Prerequisites
|
||||
- Python 3
|
||||
- Node.js + npm
|
||||
- Run from repo root
|
||||
|
||||
## Step-by-step
|
||||
### Start everything (recommended)
|
||||
```
|
||||
./dev.sh
|
||||
```
|
||||
- GUI runs in the background
|
||||
- Box runs in the foreground (you can type CLI commands)
|
||||
|
||||
### Start separately
|
||||
Box only:
|
||||
```
|
||||
python3 box/main.py run
|
||||
```
|
||||
GUI only:
|
||||
```
|
||||
cd gui
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Ports / Hosts
|
||||
- Box API: `http://127.0.0.1:8000`
|
||||
- Setup UI: `http://127.0.0.1:9000/setup`
|
||||
- GUI: `http://127.0.0.1:5174`
|
||||
|
||||
## API URL for GUI
|
||||
Default is `http://localhost:8000`. Override with:
|
||||
```
|
||||
VITE_BOX_API_URL=http://127.0.0.1:8000 npm run dev
|
||||
```
|
||||
|
||||
## Logs
|
||||
- Box logs appear in the same terminal where you run `python3 box/main.py run`.
|
||||
- GUI logs appear in the browser console.
|
||||
|
||||
## Stop / Cleanup
|
||||
- Press `Ctrl+C` in the terminal where the box is running.
|
||||
- `dev.sh` will also stop the GUI process.
|
||||
|
||||
## Checklist
|
||||
- ✅ Run `./dev.sh`
|
||||
- ✅ Box shows interactive prompt
|
||||
- ✅ GUI loads in browser
|
||||
- ✅ `curl http://127.0.0.1:8000/status` returns JSON
|
||||
|
||||
## Troubleshooting
|
||||
- Port already in use:
|
||||
- 8000 or 9000: stop other processes, or change ports in `box/main.py`.
|
||||
- CORS error in browser:
|
||||
- Ensure API is running; CORS is already enabled in the Box API.
|
||||
- GUI shows "Failed to fetch":
|
||||
- Check `VITE_BOX_API_URL` and Box API port.
|
||||
@@ -0,0 +1,53 @@
|
||||
# GUI Control Panel
|
||||
|
||||
## Purpose
|
||||
How to use the Vite-based GUI to control and observe the virtual box.
|
||||
|
||||
## Prerequisites
|
||||
- Box running on `http://127.0.0.1:8000`
|
||||
- GUI started (`npm run dev` or `./dev.sh`)
|
||||
|
||||
## Step-by-step
|
||||
1) Open GUI:
|
||||
```
|
||||
http://127.0.0.1:5174
|
||||
```
|
||||
2) Click buttons to send commands.
|
||||
3) Observe status updates (polling + refresh after command).
|
||||
|
||||
## Controls (current in GUI)
|
||||
- Play / Pause
|
||||
- Next
|
||||
- Prev
|
||||
- Vol +
|
||||
- Vol -
|
||||
- NFC UID_1 ON
|
||||
- NFC UID_1 OFF
|
||||
- Refresh Status
|
||||
|
||||
## Controls (available via API only)
|
||||
- WiFi add/reset
|
||||
- Spotify set/clear
|
||||
|
||||
Use API for those:
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"wifi_add_profile","payload":{"ssid":"HomeWiFi","password":"secret","priority":10}}'
|
||||
```
|
||||
|
||||
## Expected results
|
||||
- After any button click, status refreshes within 1 second.
|
||||
- `last_error` is visible if an error occurs.
|
||||
|
||||
## Checklist
|
||||
- ✅ GUI loads and shows API base URL
|
||||
- ✅ Status updates every 1s
|
||||
- ✅ Clicking a button updates `/status`
|
||||
|
||||
## Troubleshooting
|
||||
- GUI shows "Failed to fetch":
|
||||
- Check `VITE_BOX_API_URL`.
|
||||
- Verify Box API is running.
|
||||
- Buttons have no effect:
|
||||
- Check the API command names in `docs/api.md`.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Offline Scenarios
|
||||
|
||||
## Purpose
|
||||
Simulate online/offline behavior in the virtual box and verify status fields.
|
||||
|
||||
## Prerequisites
|
||||
- Box running on `http://127.0.0.1:8000`
|
||||
|
||||
## Step-by-step
|
||||
### WiFi offline (no profiles)
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"wifi_reset"}'
|
||||
```
|
||||
Expected:
|
||||
- `wifi_state = WIFI_UNCONFIGURED`
|
||||
- `connected_ssid = null`
|
||||
|
||||
### WiFi online
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"wifi_add_profile","payload":{"ssid":"HomeWiFi","password":"secret","priority":10}}'
|
||||
```
|
||||
Expected:
|
||||
- `wifi_state = WIFI_ONLINE`
|
||||
- `connected_ssid = HomeWiFi`
|
||||
|
||||
### Spotify unavailable
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"spotify_clear"}'
|
||||
```
|
||||
Expected:
|
||||
- `spotify_status = NOT_CONFIGURED`
|
||||
|
||||
### Spotify ready
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"spotify_set_tokens","payload":{"access_token":"a","refresh_token":"b","expires_at":123}}'
|
||||
```
|
||||
Expected:
|
||||
- `spotify_status = READY`
|
||||
|
||||
## Checklist
|
||||
- ✅ WiFi reset shows UNCONFIGURED
|
||||
- ✅ WiFi add profile shows ONLINE
|
||||
- ✅ Spotify clear shows NOT_CONFIGURED
|
||||
- ✅ Spotify set shows READY
|
||||
|
||||
## Troubleshooting
|
||||
- Status not changing:
|
||||
- Ensure `/status` is polled after sending commands.
|
||||
- Check that Box is running and secrets file is writable.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Playback Testing
|
||||
|
||||
## Purpose
|
||||
Test NFC playback, recursive media order, resume, and playback controls.
|
||||
|
||||
## Prerequisites
|
||||
- Box running: `python3 box/main.py run`
|
||||
- Media in `box/data/media/`
|
||||
|
||||
## Step-by-step
|
||||
### NFC simulation
|
||||
Start playback:
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"nfc_on","payload":{"uid":"UID_1"}}'
|
||||
```
|
||||
Stop playback:
|
||||
```
|
||||
curl -X POST http://127.0.0.1:8000/command \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"command":"nfc_off","payload":{"uid":"UID_1"}}'
|
||||
```
|
||||
|
||||
### Resume tests
|
||||
1) `nfc_on UID_1`
|
||||
2) Wait or use `tick` in CLI
|
||||
3) `nfc_off UID_1`
|
||||
4) `nfc_on UID_1` again
|
||||
Expected: position resumes from saved state.
|
||||
|
||||
### Tag switching
|
||||
1) `nfc_on UID_1`
|
||||
2) `nfc_on UID_2`
|
||||
3) `nfc_on UID_1`
|
||||
Expected: UID_1 resumes from previous position.
|
||||
|
||||
### Recursive order
|
||||
- Order is depth-first, folders first, lexicographic.
|
||||
- Change folder names or nesting to see ordering changes.
|
||||
|
||||
### End of media behavior
|
||||
- When the last file ends:
|
||||
- Playback stops
|
||||
- Position saved at end
|
||||
- State becomes IDLE
|
||||
|
||||
### Buttons
|
||||
- `next`: file_index + 1
|
||||
- `prev`: if position > 3s then position=0, else file_index - 1
|
||||
- `play_pause`: toggle PLAYING/PAUSED
|
||||
- `volume_up` / `volume_down`: change volume within 0..max
|
||||
|
||||
## Checklist
|
||||
- ✅ Resume works for same UID
|
||||
- ✅ Tag switching preserves per-UID resume
|
||||
- ✅ Recursive order matches folder structure
|
||||
- ✅ End-of-media stops playback and saves
|
||||
|
||||
## Troubleshooting
|
||||
- No playback starts:
|
||||
- Check tags in `box/data/box.json`.
|
||||
- Ensure files exist under `box/data/media`.
|
||||
- Duration is 0:
|
||||
- Filenames not matched; mock uses hash-based durations for unknown names.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Security & Storage
|
||||
|
||||
## Purpose
|
||||
Explain where data lives, what is encrypted, and how keys are derived.
|
||||
|
||||
## Prerequisites
|
||||
- Box running at least once to create `box/data/`
|
||||
|
||||
## Step-by-step
|
||||
1) Start the box:
|
||||
```
|
||||
python3 box/main.py run
|
||||
```
|
||||
2) Inspect data files:
|
||||
```
|
||||
ls -la box/data
|
||||
```
|
||||
|
||||
## Data layout
|
||||
```
|
||||
box/data/
|
||||
├── box.json # box_id, settings, tags (plaintext)
|
||||
├── state.json # resume, wifi state (plaintext)
|
||||
├── media/ # audio files
|
||||
└── secrets.enc # encrypted secrets (JSON inside)
|
||||
```
|
||||
|
||||
## What is plaintext
|
||||
- box_id
|
||||
- box name
|
||||
- volume
|
||||
- resume positions
|
||||
- playback state
|
||||
- media paths
|
||||
- UI state
|
||||
|
||||
## What is encrypted
|
||||
- WiFi profiles
|
||||
- Spotify tokens
|
||||
- Server tokens (future)
|
||||
|
||||
## Key derivation
|
||||
- Key = PBKDF2-HMAC-SHA256(box_id + STATIC_SALT)
|
||||
- Key is never stored on disk
|
||||
- secrets.enc is not portable between boxes
|
||||
|
||||
## Reset behavior
|
||||
- WiFi reset: removes only wifi_profiles from secrets.enc
|
||||
- Factory reset: delete `box/data/box.json`, `box/data/state.json`, `box/data/secrets.enc`
|
||||
|
||||
## Checklist
|
||||
- ✅ `secrets.enc` exists after WiFi/Spotify set
|
||||
- ✅ `box.json` contains `box_id`
|
||||
- ✅ No secrets appear in `/status`
|
||||
|
||||
## Troubleshooting
|
||||
- secrets.enc not created:
|
||||
- Ensure you ran `wifi_add_profile` or `spotify_set_tokens`.
|
||||
- secrets.enc unreadable after reset:
|
||||
- Factory reset creates a new box_id and new key.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Setup WebGUI
|
||||
|
||||
## Purpose
|
||||
Configure WiFi profiles in the virtual box without touching the API or CLI.
|
||||
|
||||
## Prerequisites
|
||||
- Box running: `python3 box/main.py run`
|
||||
|
||||
## Step-by-step
|
||||
1) Open the Setup UI:
|
||||
```
|
||||
http://127.0.0.1:9000/setup
|
||||
```
|
||||
2) Choose SSID and enter password.
|
||||
3) Click "Verbinden".
|
||||
4) Refresh `/status` to see `wifi_state` and `connected_ssid`.
|
||||
|
||||
## Fields
|
||||
- SSID: drop-down from mock scan
|
||||
- Password: free text
|
||||
|
||||
## Expected results
|
||||
- WiFi profile is saved (encrypted)
|
||||
- `wifi_state` becomes `WIFI_ONLINE`
|
||||
- `connected_ssid` matches selected SSID
|
||||
|
||||
## Checklist
|
||||
- ✅ Setup UI loads
|
||||
- ✅ Submit stores a profile
|
||||
- ✅ `/status` reflects `WIFI_ONLINE`
|
||||
|
||||
## Troubleshooting
|
||||
- Setup UI not reachable:
|
||||
- Ensure Box is running and port `9000` is free.
|
||||
- Submit does nothing:
|
||||
- Check Box logs for errors; secrets file must be writable.
|
||||
|
||||
## Notes
|
||||
- Setup UI is write-enabled only when no profiles exist.
|
||||
- When profiles exist, the page switches to read-only status.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Storage (Legacy Notes)
|
||||
|
||||
## Purpose
|
||||
This file is kept for backward reference. Current storage documentation lives in `docs/security-storage.md`.
|
||||
|
||||
## Prerequisites
|
||||
- None
|
||||
|
||||
## Step-by-step
|
||||
- See `docs/security-storage.md`.
|
||||
|
||||
## Troubleshooting
|
||||
- If you ended up here from older links, update them to `docs/security-storage.md`.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Virtual Box Flow (IDE)
|
||||
|
||||
## Purpose
|
||||
Describe the full, hardware-free box lifecycle used in development.
|
||||
|
||||
## Prerequisites
|
||||
- Python 3
|
||||
- Box started with `python3 box/main.py run`
|
||||
|
||||
## Step-by-step
|
||||
1) Box starts and creates `box/data/box.json` if missing.
|
||||
2) WiFi state is derived from stored profiles:
|
||||
- none -> `WIFI_UNCONFIGURED`
|
||||
3) Setup UI available at `http://127.0.0.1:9000/setup`.
|
||||
4) After profile submission, box becomes `WIFI_ONLINE`.
|
||||
5) API available at `http://127.0.0.1:8000`.
|
||||
|
||||
## Troubleshooting
|
||||
- Setup UI not reachable:
|
||||
- Ensure port 9000 is free and Box is running.
|
||||
- API not reachable:
|
||||
- Ensure port 8000 is free and Box is running.
|
||||
Reference in New Issue
Block a user