release: Mark VIII 1.0
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
# Pager WebUI — Design Spec (v1)
|
||||
|
||||
- **Date:** 2026-08-10
|
||||
- **Status:** Approved (pending written-spec review)
|
||||
- **Owner:** Hak5 WiFi Pineapple Pager expansion project
|
||||
|
||||
## 1. Goal
|
||||
|
||||
Build a Mark VII-style web management UI that runs **on the WiFi Pineapple Pager**
|
||||
itself, with core-parity featureset (Dashboard, PineAP, Recon, Handshakes/Loot,
|
||||
Payloads, Logs, Settings, and a bottom-docked terminal), packaged as a
|
||||
Payload-Portal-installable payload and deployed over SSH/SCP.
|
||||
|
||||
The UI is reached at `http://172.16.52.1:8080/` (verified free on the device).
|
||||
|
||||
## 2. Verified Research Basis (live devices)
|
||||
|
||||
### Pager (172.16.52.1)
|
||||
- MediaTek MT76x8 SoC, OpenWRT-based `Pineapple Pager 24.10.1`
|
||||
(`ramips/mt76x8`, `mipsel_24kc`, Linux 6.6.86).
|
||||
- Full root SSH (`root` + device password). `opkg` available.
|
||||
- Persistent 4GB MMC: `/root` -> `/mmc/root`; payloads live under
|
||||
`/root/payloads/`, loot under `/root/loot/`.
|
||||
- Tools present: `python3` (3.11.14), `sqlite3`, `iwinfo`, `hostapd_cli`,
|
||||
`ubus`, `uci`, `curl`, `nc`, `wget`.
|
||||
- Firmware is U-Boot **signed** — firmware modification is out of scope; no
|
||||
stock files are touched.
|
||||
|
||||
### Hak5 daemon (`/pineapple/pineapple`, Go)
|
||||
- HTTP API on `:1471` and an unauthenticated Unix socket `/tmp/api.sock`
|
||||
serving the same router.
|
||||
- Auth: `POST /api/login` (`{"username":"root","password":...}`) returns
|
||||
`{"token": ...}`. Requests authorize with
|
||||
`Authorization: Bearer <token>` or the `AUTH_<serverid>` cookie
|
||||
(serverid from `/api/api_ping`, e.g. `001337AEE050`).
|
||||
- Existing API used by the stock Virtual Pager:
|
||||
`api_ping`, `login`, `payloads/portal/{index,refresh,updates,<key>/install,<key>/remove}`,
|
||||
`loot/archive`, `loot/zip`, `files/zip/root/loot/handshakes`,
|
||||
`terminal/openWs` (WS), `pager/input/keys.ws` (WS), `pager/display/screen.ws` (WS).
|
||||
- Terminal WS `/api/terminal/openWs`: plain-text WebSocket (keystrokes in,
|
||||
output out). Requires the `AUTH_*` cookie (verified 401 without, 101 with).
|
||||
Accepts cross-origin handshakes. Cookies are host-scoped and **port-agnostic**,
|
||||
and the `:8080` page and `:1471` host are the same site, so a cookie set for
|
||||
host `172.16.52.1` is sent on the WS handshake from the `:8080` page. The
|
||||
docked terminal therefore connects **directly** to the daemon WS; a
|
||||
server-side relay is the documented fallback.
|
||||
|
||||
### Control channel (payload interface)
|
||||
- `/usr/bin/hak5cmd` (C++, protobuf client to the daemon). 49 symlinks provide
|
||||
every PineAP operation, e.g.:
|
||||
`PINEAPPLE_SSID_POOL_{ADD,ADD_FILE,START,STOP,LIST,DELETE,CLEAR,COLLECT_START,COLLECT_STOP}`,
|
||||
`PINEAPPLE_NETWORK_FILTER_{MODE,ADD,ADD_FILE,DELETE,LIST,CLEAR}`,
|
||||
`PINEAPPLE_DEVICE_FILTER_{MODE,ADD,ADD_FILE,DELETE,LIST,CLEAR}`,
|
||||
`PINEAPPLE_MIMIC_{ENABLE,DISABLE}`,
|
||||
`PINEAPPLE_DEAUTH_CLIENT`, `PINEAPPLE_EXAMINE_{BSSID,CHANNEL,RESET}`,
|
||||
`PINEAPPLE_HOPPING_{START,STOP}`, `PINEAPPLE_SET_BANDS`,
|
||||
`PINEAPPLE_RECON_NEW`, `PINEAPPLE_LOOT_ARCHIVE`.
|
||||
- Verified: commands run from CLI over SSH (read-only ones confirmed).
|
||||
|
||||
### Recon data
|
||||
- SQLite `/root/recon/recon.db`: tables `scan`, `wifi_device`, `ssid`,
|
||||
`handshake`, `hostap_chalresp`, `hostap_basic`, `hostap_client`,
|
||||
`hostap_handshake`.
|
||||
|
||||
### PineAP config
|
||||
- UCI file `/etc/config/pineapd` (sections: `pineapd`, `hostapd`,
|
||||
`ssidpool`, `ssid_filter`, `mac_filter`, `interface wlan0mon/wlan1mon/wlan2mon`).
|
||||
- Reload trigger exists (`/etc/init.d/pineapd reload`, `pineap_reload`).
|
||||
|
||||
### Precedents (payloads already on device)
|
||||
- `nautilus` (`user/remote_access/nautilus`): web UI payload with init script
|
||||
(`nautilus.init`, START=99, procd), python3 proxy, foreground/background run
|
||||
modes, `PAYLOAD_GET_CONFIG` persistence.
|
||||
- `virtual_pager_enhancer`: uhttpd+CGI on port 4040 (init script pattern).
|
||||
|
||||
### Mark VII blueprint
|
||||
- 113 `/api/*` endpoints extracted from its Angular bundle:
|
||||
dashboard, `pineap/*` (clients, kick, deauth, filters, handshakes, settings,
|
||||
ssids, summary), `recon/*` (scans, start/stop/status, tags), logging, settings/
|
||||
networking, modules, device, terminal (xterm.js bottom-docked panel).
|
||||
|
||||
## 3. Repo Layout
|
||||
|
||||
Dev workspace: `C:\Users\root\Documents\Pineapple\pager-webui\`
|
||||
|
||||
```
|
||||
pager-webui\
|
||||
├── payload\user\general\pager-webui\
|
||||
│ ├── _hak5_manifest.json
|
||||
│ ├── payload.sh # run-mode installer (nautilus pattern)
|
||||
│ ├── pagerwebui.init # OpenWRT init template (START=99, procd, respawn)
|
||||
│ ├── server.py # Python3 stdlib HTTP+WS+JSON API backend (:8080)
|
||||
│ └── www\ # vanilla JS SPA + xterm.js bundle
|
||||
├── scripts\
|
||||
│ ├── deploy.ps1 # build portal zip + SCP/install to Pager
|
||||
│ └── dev.ps1 # local dev server w/ proxy to Pager
|
||||
├── docs\specs\ # design specs
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 4. Packaging & Deployment
|
||||
|
||||
- **Payload format** mirrors `nautilus` exactly: self-contained directory
|
||||
`user/general/pager-webui/` with `payload.sh`, `pagerwebui.init`, `server.py`,
|
||||
`www/`.
|
||||
- **Sideload (v1 delivery):** `scripts/deploy.ps1` builds a portal-format zip
|
||||
(`payload-<b64>.zip`) and installs it to
|
||||
`/root/payloads/user/general/pager-webui/` on the Pager over SCP. The payload
|
||||
then appears in the on-device Payloads menu and the Virtual Pager's portal
|
||||
view — installable like any Payload Portal payload.
|
||||
- **Future portal distribution:** packaging is drop-in ready for a PR to
|
||||
`hak5/wifipineapplepager-payloads`; the build script generates the manifest
|
||||
`time` / `last_hash` / `zip` fields.
|
||||
|
||||
### `payload.sh` run flow (nautilus pattern)
|
||||
|
||||
1. If `/etc/init.d/pagerwebui` exists and `running`:
|
||||
show URL `http://172.16.52.1:8080/`, offer
|
||||
`CONFIRMATION_DIALOG "Stop service?"`; on confirm -> `stop`, `disable`,
|
||||
remove init script; exit.
|
||||
2. Read `PAYLOAD_GET_CONFIG pager_webui auto_mode` / `run_mode`. If
|
||||
`auto_mode=true`, skip prompt (background if `run_mode=background`, else
|
||||
foreground).
|
||||
3. Else `CONFIRMATION_DIALOG "Run as background service?"`:
|
||||
- **Yes -> background:** `cp pagerwebui.init /etc/init.d/pagerwebui`,
|
||||
`chmod +x`, `enable`, `start` (procd runs `python3 server.py`, respawns on
|
||||
crash). Boot-persistent via rc.d symlinks.
|
||||
- **No -> foreground:** spawn `python3 server.py` with
|
||||
`/tmp/pagerwebui.pid`, show URL, loop `WAIT_FOR_INPUT` until B/Escape,
|
||||
`trap cleanup` kills the server and removes the pid file.
|
||||
4. Guard: python3 is present on current firmware; init script fails gracefully
|
||||
if missing.
|
||||
|
||||
- **Uninstall:** the stop path above, plus deleting the payload directory
|
||||
(portal semantics).
|
||||
- **Boot persistence:** rc.d symlinks (overlay). Survives reboots and firmware
|
||||
upgrades; after a firmware upgrade (which wipes overlay) re-run the payload to
|
||||
re-enable — same caveat as nautilus. Foreground mode needs no persistence.
|
||||
|
||||
## 5. Backend (`server.py`)
|
||||
|
||||
Python 3.11 stdlib only (`http.server`, `sqlite3`, `subprocess`, `json`,
|
||||
`socketserver`, hand-rolled minimal RFC6455 for the live-update WS). Binds
|
||||
`0.0.0.0:8080`. Single origin serves the SPA and the API.
|
||||
|
||||
| Endpoint | Method | Implementation |
|
||||
|---|---|---|
|
||||
| `/api/login` | POST | validate via daemon `:1471/api/login`; on success return token and `Set-Cookie: AUTH_<serverid>` (host `172.16.52.1`, no `Domain`, `Path=/`, `HttpOnly`, `SameSite=Lax`) so docked terminal + loot downloads on `:1471` are authorized cross-port |
|
||||
| `/api/api_ping` | GET | serverid + version (mirror daemon) |
|
||||
| `/api/status` | GET | battery/power via sysfs, WiFi/interfaces via `iwinfo` + `ip`, firmware/daemon versions, disk via `df`, uptime |
|
||||
| `/api/pineap/settings` | GET/POST | read/write UCI `/etc/config/pineapd` (mimic, collect probes, advertise, collect handshakes, random MAC, wigle, bands) + `pineap_reload` |
|
||||
| `/api/pineap/ssids` | GET/POST | SSID pool read/write via `hak5cmd` |
|
||||
| `/api/pineap/ssidpool/{start,stop,collect_start,collect_stop}` | POST | via `hak5cmd` |
|
||||
| `/api/pineap/filters/client` | GET/POST | device filter mode + list via `hak5cmd` |
|
||||
| `/api/pineap/filters/ssid` | GET/POST | network filter mode + list via `hak5cmd` |
|
||||
| `/api/pineap/clients` | GET | associated clients via `iwinfo assoclist` / `hostapd_cli` on `wlan0open`/`wlan0wpa`/`wlan0mgmt` |
|
||||
| `/api/pineap/clients/kick` | POST | deauth via `hak5cmd` + auto-add to deny filter (Mark VII behavior) |
|
||||
| `/api/pineap/deauth/client` | POST | `PINEAPPLE_DEAUTH_CLIENT` |
|
||||
| `/api/recon/{start,stop}` | POST | `hak5cmd` `RECON_NEW` / stop |
|
||||
| `/api/recon/scans` | GET | scans list from `recon.db` |
|
||||
| `/api/recon/scans/<id>` | GET | APs/clients/handshakes for a scan from `recon.db` |
|
||||
| `/api/pineap/handshakes` | GET/DELETE | list/delete `/root/loot/handshakes` |
|
||||
| `/api/loot/zip` | GET | zip download (wraps daemon `:1471` with cookie) |
|
||||
| `/api/loot/archive` | POST | wraps daemon `:1471` |
|
||||
| `/api/payloads/index`, `/api/payloads/install`, `/api/payloads/remove`, `/api/payloads/refresh` | GET/POST | wrap daemon portal endpoints |
|
||||
| `/api/logging/system` | GET | `logread` (filtered, tail) |
|
||||
| `/api/logging/pineap` | GET | pineapd/daemon log sources |
|
||||
| `/api/device` | GET | hostname, MACs, model |
|
||||
| `/api/settings/hostname` | GET/POST | `uci` network hostname |
|
||||
| `/api/settings/password` | POST | change the device root password via BusyBox `passwd` stdin |
|
||||
| `/api/settings/ntp` | GET/POST | UCI `system` `timeserver` (enabled + servers) + restart `sysntpd` |
|
||||
| `/api/ws` | WS | live push: status/clients/recon deltas every ~2s |
|
||||
| `/api/terminal/openWs` | WS | same path on our origin; client connects direct to daemon `ws://172.16.52.1:1471/api/terminal/openWs` (cookie-authed). Fallback: server relays |
|
||||
|
||||
### Auth model
|
||||
- All endpoints (except `/api/login`) require a valid session cookie set by
|
||||
`/api/login`.
|
||||
- Token is never logged or stored server-side beyond the session check; the
|
||||
backend validates each request by checking the session cookie against the
|
||||
daemon's token (a lightweight session store in `/tmp/pagerwebui.session`).
|
||||
- Commands are executed with argument lists (no shell string interpolation) to
|
||||
prevent injection.
|
||||
|
||||
## 6. Frontend (vanilla JS SPA)
|
||||
|
||||
- Static files in `www/`: `index.html`, `css/app.css`, `js/app.js` (or split
|
||||
modules), `js/xterm.js` + `js/xterm-fit.js` (bundled copies), `assets/`.
|
||||
- Mark VII-style chrome: dark theme, top bar (logo, live status, **Terminal
|
||||
button**), nav rail, hash-based routing (`#/dashboard`, `#/pineap`,
|
||||
`#/recon`, `#/handshakes`, `#/payloads`, `#/logs`, `#/settings`).
|
||||
- **Dashboard:** status cards + live counters (battery, clients, APs,
|
||||
handshakes) fed by `/api/ws`.
|
||||
- **PineAP:** settings toggles (mimic/advertise/collect/handshakes/random MAC/
|
||||
wigle/bands), SSID pool CRUD + collect/start/stop, client & SSID filters
|
||||
(mode + list CRUD), client list with kick.
|
||||
- **Recon:** scan list, AP/client tables from `recon.db`, start/stop buttons.
|
||||
- **Handshakes/Loot:** list, download zip, delete, archive.
|
||||
- **Payloads:** portal list + install/remove/refresh.
|
||||
- **Logs:** system + pineap logs with tail/poll.
|
||||
- **Settings:** hostname, NTP, password, webUI prefs (poll interval, accent),
|
||||
service status (background/foreground).
|
||||
- **Terminal:** bottom-docked xterm panel toggled by the top-bar button (Mark
|
||||
VII parity). Connects `ws://172.16.52.1:1471/api/terminal/openWs`. Default
|
||||
80x24; resize behavior validated during implementation (daemon may ignore
|
||||
resize; fallback fixed size with xterm `fit` disabled).
|
||||
|
||||
## 7. Security & Resilience
|
||||
|
||||
- Auth: device password validated through the daemon; HttpOnly session cookie;
|
||||
no plaintext secret storage; state-changing endpoints all behind login.
|
||||
- No stock files modified; no `opkg` changes; reversible via `payload.sh`
|
||||
stop/uninstall; factory reset / firmware recovery remain available.
|
||||
- `server.py` failure modes: procd respawn in background mode; foreground mode
|
||||
cleans up on exit; `recon.db` opened read-only; subprocesses use arg lists.
|
||||
- Binds `0.0.0.0:8080` (same exposure class as stock `:1471` / `:7681`).
|
||||
|
||||
## 8. Testing & Verification
|
||||
|
||||
- Windows dev loop: `scripts/dev.ps1` runs the SPA + API locally and proxies to
|
||||
the Pager.
|
||||
- PowerShell-driven API tests against `:8080`: login, status, each read/write
|
||||
endpoint before frontend wiring.
|
||||
- On-device smoke tests per page: status, pool CRUD, filter toggles, recon
|
||||
start/scan read, handshake listing, portal install/remove, terminal I/O,
|
||||
background vs foreground modes, reboot persistence.
|
||||
- Recovery drill: uninstall, re-install, foreground-stop, firmware-upgrade
|
||||
caveat documented in README.
|
||||
|
||||
## 9. Out of Scope (v1)
|
||||
|
||||
- `:1471` takeover/redirect.
|
||||
- Mark VII features without a Pager equivalent: Campaigns, Modules, Cloud C²,
|
||||
Enterprise/EAP pages.
|
||||
- Physical-display screen mirror.
|
||||
- Publishing a PR to the official payloads repo (packaging ready; submission
|
||||
later).
|
||||
|
||||
## 10. Open Risks (mitigated during implementation)
|
||||
|
||||
- Client-list source validation: `iwinfo assoclist` / `hostapd_cli` against the
|
||||
Pager's hostapd interfaces (`wlan0open`, `wlan0wpa`, `wlan0mgmt`).
|
||||
- Minimal RFC6455 WebSocket server correctness.
|
||||
- Daemon terminal resize support (fallback to fixed 80x24).
|
||||
@@ -0,0 +1,176 @@
|
||||
# Pineapple UI Clone — Design Spec
|
||||
|
||||
- **Date:** 2026-08-11
|
||||
- **Status:** Approved (pending written-spec review)
|
||||
- **Owner:** Hak5 WiFi Pineapple Pager expansion project
|
||||
- **Supercedes look of:** `www/` assets shipped in `2026-08-10-pager-webui-design.md`
|
||||
|
||||
## 1. Goal
|
||||
|
||||
Restyle the Pager WebUI (`http://172.16.52.1:8080/`) to be a faithful clone of
|
||||
the stock Hak5 WiFi Pineapple UI (`http://172.16.42.1:1471/`), so an operator
|
||||
used to one interface can use the other without re-learning navigation,
|
||||
terminology, or interaction patterns.
|
||||
|
||||
Scope is **cosmetic + navigation only**, plus one small read-only backend
|
||||
endpoint (`GET /api/pineap/aps`, §3.5). Auth/session mechanics and the payload
|
||||
packaging pipeline are unchanged.
|
||||
|
||||
Verified on-device (2026-08-11): the Pager's Go daemon on `:1471` exposes only
|
||||
`api_ping`, `login`, payload-portal, loot, and WS endpoints — it has **no**
|
||||
`/api/pineap/*` surface. All PineAP/Recon/Logging/Settings endpoints in the
|
||||
current `server.py` are implemented by pager-webui itself via `hak5cmd`,
|
||||
`uci`, `iwinfo`, and `recon.db`. (Note: the old UI at `172.16.42.1:1471` and
|
||||
the new Pager at `172.16.52.1` are separate devices.)
|
||||
|
||||
## 2. Research Basis (live UIs, captured 2026-08-11)
|
||||
|
||||
### Old UI (:1471) — stock Angular 8 / Angular Material SPA
|
||||
- Hash routes: `#/Login`, `#/Setup`, `#/Dashboard`, `#/Campaigns`
|
||||
(`/reports`), `#/Recon` (`/handshakes`), `#/PineAP` (`/open`, `/clients`,
|
||||
`/filtering`, `/enterprise`, `/aps`, `/impersonation`), `#/Settings`
|
||||
(`/networking`, `/wifi`, `/developer`, `/advanced`, `/led`, `/help`),
|
||||
`#/Logging` (`/system`), `#/Modules`.
|
||||
- **Login:** full-screen flat gray `#9c9c9c`; centered white elevated card
|
||||
(`mat-elevation-z20`): "WiFi Pineapple" `h2`, pineapple logo PNG (148px),
|
||||
Username + Password fields, raised "Login" button (spinner while busy),
|
||||
inline red error text; Cloud C2 error variant.
|
||||
- **Shell:** 64px toolbar (`#424242`, Material `mat-toolbar`) with logo + "WiFi
|
||||
Pineapple"; content offset `margin-left: 90px`; icon rail sidenav
|
||||
(`min-width:60px`, `#f3f3f3`; dark `#3a3a3a`, hover `#a9a9a9` / dark
|
||||
`#545454`): **Dashboard, Campaigns, PineAP ("PineAP Suite"), Recon, Logging,
|
||||
Modules ("Modules & Packages"), Settings**; active entry `border-right:3px
|
||||
solid #1976d2`; entry dividers; bottom "Open Menu" chevron toggles expanded
|
||||
rail; module entries are drag-reorderable (out of scope). Content background
|
||||
`#fafafa`; Roboto/Helvetica/sans-serif font stack.
|
||||
- **Views use horizontal `mat-tab` navigation with a blue ink bar** for each
|
||||
multi-page section (PineAP, Recon, Logging, Settings, Campaigns).
|
||||
- **Dashboard:** status cards (Clients, Handshakes Captured, Disk Usage, …) +
|
||||
Chart.js line chart (clients over time) + "Connected Clients" table
|
||||
(Deauthenticate) + "Captured WPA Handshakes" table.
|
||||
- **Extras:** keyboard shortcuts (`D`/`C`/`R`/`P`/`M`, Backquote = terminal),
|
||||
light/dark theme (stored in `localStorage`), notification center, corner
|
||||
"flash indicator" toasts, ASCII pineapple `(='.'=)`.
|
||||
- **Auth:** `POST /api/login` `{username, password}` → `{token}`; stored in
|
||||
`localStorage` `<base>_authToken` + `AUTH_<ServerId>` cookie; device password
|
||||
for user `root`.
|
||||
|
||||
### New UI (:8080) — vanilla JS SPA (current source of truth)
|
||||
- GitHub-dark theme (`#0d1117` bg, `#161b22` panels, teal `#00d4aa` accent,
|
||||
Segoe UI); password-only login; flat text rail (Dashboard, PineAP, Recon,
|
||||
Handshakes, Payloads, Logs, Settings); single-page sections; bottom-docked
|
||||
xterm panel; WS live updates + 5s polling fallback; bottom-right toasts.
|
||||
- Backend: pure-socket HTTP/JSON/WS on `0.0.0.0:8080` (device
|
||||
`python3-light`); auth via `AUTH_<serverid>` HttpOnly cookie validated
|
||||
against the daemon; terminal connects directly to daemon WS on `:1471`.
|
||||
|
||||
### Feature mapping (old IA → current Pager capabilities)
|
||||
| Old tab | Clone behaviour |
|
||||
|---|---|
|
||||
| Dashboard | status cards + Chart.js chart + Connected Clients + Handshakes tables |
|
||||
| Campaigns | visible tab, single "not supported on the Pager" empty-state card |
|
||||
| PineAP → Open | PineAP settings toggles (mimic/advertise/probes/handshakes/random MAC/WiGLE) + bands |
|
||||
| PineAP → Clients | connected clients + kick |
|
||||
| PineAP → Filtering | client (MAC) + SSID allow/deny/off filters |
|
||||
| PineAP → APs | **new read-only endpoint** `GET /api/pineap/aps`: `iwinfo <mon-iface> scan` table (BSSID/SSID/Channel/Signal/Encryption) |
|
||||
| PineAP → Impersonation | SSID pool add/clear + Start/Stop/Collect |
|
||||
| PineAP → Enterprise | **omitted** (not supported on Pager) |
|
||||
| Recon → Overview | scans list + new/stop/refresh + scan detail |
|
||||
| Recon → Handshakes | loot files: download zip / archive / delete |
|
||||
| Logging → Overview | system + PineAP logs |
|
||||
| Logging → System | system log with level filter (Error/Warning/Informational) |
|
||||
| Modules & Packages | payload portal (search + list + Install/Remove) |
|
||||
| Settings | general info, hostname, NTP, password, WebUI prefs (poll interval, theme) |
|
||||
|
||||
## 3. Design
|
||||
|
||||
### 3.1 Architecture
|
||||
No build step; same vanilla-JS file layout. New/vendored files under `www/`:
|
||||
|
||||
- `assets/logo.png` + favicon — copied from old UI `assets/icons/logo.png`.
|
||||
- `js/chart.min.js` — vendored Chart.js from old UI (no CDN on device).
|
||||
- `js/icons.js` — inline SVG icon set lifted from the old Angular bundle
|
||||
(dashboard grid, campaigns, pineap, recon, logging, modules, settings,
|
||||
chevron).
|
||||
- `js/themes.css` or CSS custom properties — light/dark token sets.
|
||||
- `css/app.css` — rewritten around Material light tokens.
|
||||
- `js/views.js` — restructured to old IA with sub-views + `mat-tab`-style bars.
|
||||
- `js/app.js` — routing (incl. sub-routes), keyboard shortcuts, theme toggle,
|
||||
terminal wiring, flash-style toasts.
|
||||
- `index.html` — old-style shell markup (login card, toolbar, icon rail,
|
||||
content, terminal panel).
|
||||
|
||||
Roboto: vendor `.woff2` from the device if present (`:1471/assets/` fonts);
|
||||
otherwise the existing `Roboto, Helvetica Neue, sans-serif` stack falls back to
|
||||
system fonts.
|
||||
|
||||
### 3.2 Design tokens (light default, dark optional)
|
||||
- Light: content `#fafafa`; cards `#fff` with subtle elevation/shadow; toolbar
|
||||
+ rail `#424242`; rail hover `#a9a9a9`; active border `#1976d2`; primary
|
||||
`#1976d2` / `#1e88e5`; danger `#d32f2f`; ok `#7cb342`; warn `#f9a825`; text
|
||||
`#212121` / muted `#686868`; ink bar + focus `#1976d2`.
|
||||
- Dark (mirrors old theme): rail `#3a3a3a`, hover `#545454`, surfaces `#303030`,
|
||||
cards `#424242`.
|
||||
- Theme selected via `<html class="dark">` driven by `localStorage`; toggle in
|
||||
Settings (and honored on all pages).
|
||||
|
||||
### 3.3 Shell
|
||||
- **Toolbar (64px, `#424242`):** logo + "WiFi Pineapple" brand (left); right:
|
||||
muted live status "BAT % · CLIENTS n", Terminal button.
|
||||
- **Icon rail (60px):** 7 entries, 24px inline SVG + label (label hidden while
|
||||
collapsed, `title` tooltip shown), dividers between groups, active = 3px blue
|
||||
right border. Bottom "Open Menu" chevron expands to ~200px with labels;
|
||||
state persisted in `localStorage` (mirrors old `sideNavState`).
|
||||
- **Content (`#fafafa`):** page header + horizontal tab bar (where applicable)
|
||||
+ white cards; existing `.section`/`.tbl`/`.badge`/`.row`/`.toggle` classes
|
||||
restyled to the light theme.
|
||||
- **Terminal:** stays bottom-docked (new behaviour) but restyled to the old
|
||||
look; kept docked intentionally (matches current Pager UX and spec v1).
|
||||
- **Toasts:** corner "flash indicator" style (old look), same API.
|
||||
|
||||
### 3.4 Login
|
||||
Password-only (per user decision; username fixed `root`). Full-screen gray
|
||||
`#9c9c9c`; centered white elevated card: logo, "WiFi Pineapple" `h2`, single
|
||||
Password field (placeholder "Password"), raised primary Login button with busy
|
||||
spinner, inline red error text on failure. Posts to the existing `/api/login`
|
||||
endpoint via `PagerAPI.login('root', pw)` — **no backend change**.
|
||||
|
||||
### 3.5 Views (per mapping table)
|
||||
Each multi-page section renders a `mat-tab`-style horizontal bar (blue ink
|
||||
bar) with tab items; deep-linkable via hash routes `#/pineap/clients` etc.
|
||||
Placeholder Campaigns uses the old empty-state card.
|
||||
|
||||
**PineAP → APs** requires one new backend route. Add to `server.py`:
|
||||
`GET /api/pineap/aps` → runs `iwinfo <iface> scan` over the monitor interfaces
|
||||
listed by `/api/status` and returns rows `{bssid, ssid, channel, signal,
|
||||
encryption}` (read-only, no root action, same exposure class as the existing
|
||||
`/api/status`). A unit test covers the parser with a canned `iwinfo` capture.
|
||||
|
||||
### 3.6 Data flow
|
||||
Unchanged: `PagerAPI` (fetch wrapper), `Live` WS + 5s poll fallback, `Live.onTick`
|
||||
drives the dashboard chart's rolling series (e.g. last 60 samples of clients +
|
||||
handshakes). Theme and rail state live in `localStorage`. The single new route
|
||||
is `GET /api/pineap/aps` (§3.5).
|
||||
|
||||
### 3.7 Error handling
|
||||
Unchanged: failed API calls surface via toasts; login failure shows inline red
|
||||
text; WS down → poll fallback (existing logic untouched).
|
||||
|
||||
## 4. Testing
|
||||
|
||||
- Manual on-device smoke pass per spec v1 §8: every page in background and
|
||||
foreground modes, login/logout, terminal I/O, reboot persistence.
|
||||
- Visual parity checklist: login card, toolbar, rail expand/collapse + active
|
||||
indicator, each tab bar, table/card styling, dark theme.
|
||||
- Asset checks: `logo.png`, favicon, `chart.min.js`, Roboto (if vendored) all
|
||||
serve from `:8080`; verify with `curl`.
|
||||
- Existing Python `unittest` suite (API-level) must remain green; add a test for
|
||||
the new `iwinfo` scan parser.
|
||||
- Deploy via `scripts/deploy.ps1` (existing pipeline); payload zip must include
|
||||
the new/vendored assets.
|
||||
|
||||
## 5. Out of scope
|
||||
|
||||
- Campaigns functionality, Cloud C2, Enterprise SSIDs, LED/Network/Developer
|
||||
Settings sub-pages, module drag-reorder, notification center, `:1471`
|
||||
takeover.
|
||||
Reference in New Issue
Block a user