Commit Graph

611 Commits

Author SHA1 Message Date
eebc84d0b9 fix(zigbee2mqtt): Fix adapter type, config format, and add MQTT dependency
The z2m 2.x breaking changes required three fixes discovered during
live deployment testing on the router:
- Adapter renamed from `ezsp` to `ember` in zigbee-herdsman 4.0.0
- Config format needs `version: 4` and nested `homeassistant.enabled`
- Start script needs `ZIGBEE2MQTT_DATA` env var for correct config path
- Add `mosquitto-nossl` as package dependency (MQTT broker required)
- Direct `/dev/ttyUSB0` passthrough works; socat TCP bridge does not

Also updates project planning files (HISTORY.md, TODO.md, WIP.md,
CLAUDE.md) and rebuilds bonus feed with latest IPKs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 19:29:59 +01:00
acd7e87e56 chore(bonus-feed): Rebuild feed with zigbee2mqtt LXC and device-intel fixes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:33:18 +01:00
f4157811c5 fix(device-intel): Fix empty vendor column and add OUI emoji display
- Fix wrong mac-guardian DB path (clients.db -> known.db) in 3 files
- Add standalone OUI vendor fallback for ARP/DHCP-only devices
- Expand oui.tsv from ~30 to 100+ entries (GL.iNet, Bosch, Samsung, Docker, etc.)
- Add vendorDisplay() with emoji prefixes for MAC types:
  container, virtual, randomized, IoT, mesh peer

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:33:10 +01:00
c5d40cf464 feat(zigbee2mqtt): Rewrite from Docker to LXC Alpine container
Replace Docker-based zigbee2mqtt with a KISS LXC approach using Alpine
Linux container with Node.js + zigbee2mqtt, matching the HAProxy LXC
pattern. Adds USB serial passthrough for Sonoff Dongle Lite MG21.

- zigbee2mqttctl: Full LXC lifecycle (install, update, check, shell)
- RPCD: LXC diagnostics (lxc, cp210x, serial, container, service)
- api.js: Fix callApply missing params (payload was silently dropped)
- overview.js: Match new LXC diagnostics, fix applyConfig call
- Makefiles: Replace +dockerd +docker +containerd with +lxc +kmod-usb-serial-cp210x

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:32:57 +01:00
eab2e5d159 chore(bonus-feed): Rebuild feed with jellyfin ipk and latest fixes
Includes rebuilt packages with RPCD function wrapper fix, crowdsec
decisions fix, and new secubox-app-jellyfin package.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:07:54 +01:00
64fb579248 feat(exposure): Sort services by DNS domain names first, then by port
Services with HAProxy DNS domains are now displayed at the top of the
table sorted alphabetically by domain, followed by remaining services
sorted by port number.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:07:48 +01:00
155f9d8005 feat(jellyfin): Add uninstall, update, backup, HAProxy integration and LuCI actions
- Add jellyfinctl commands: uninstall, update, backup, configure-haproxy
- Add RPCD methods: uninstall, update, backup, configure_haproxy
- Add domain and disk_usage to status display
- Add action buttons in LuCI overview: Update, Backup, Configure HAProxy, Uninstall
- Add UCI options: domain, backup_path, haproxy_enabled

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:10:44 +01:00
b32a0c222b chore(bonus-feed): Rebuild all feed packages with latest fixes
Includes device-intel, dns-provider, crowdsec-dashboard, and jellyfin
packages plus updated Packages index.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:07:19 +01:00
e1d70c5bac fix(crowdsec-dashboard): Fix decisions list empty due to wrong RPC expect key
The callDecisions RPC declaration used expect: { alerts: [] } but the
backend returns { decisions: [...] }, causing the unwrapped result to
always be empty. Also removed leftover console.log debug statements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:00:46 +01:00
f561dda7a2 fix(rpcd): Wrap call handlers in function for BusyBox ash local keyword compatibility
BusyBox ash rejects `local` outside a function. Both RPCD handlers used
`local` directly in the case block, causing "not in a function" errors
and silent RPC failures (empty responses).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:39:50 +01:00
78802f2850 fix(luci): Fix menu navigation and settings Save & Apply for device-intel and dns-provider
- Change menu action type from "firstchildview" to "firstchild" to fix runtime exception
- Remove null handleSaveApply/handleSave/handleReset so form.Map default save works
- Update Gandi API link from defunct account.gandi.net to admin.gandi.net PAT page

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:22:11 +01:00
abc0f66246 fix(device-intel): Fix BusyBox compatibility and data source mapping
- Replace bash-only $((16#hex)) with printf "%d" 0x for ash
- Fix client-guardian collector to use actual UCI fields (name, zone,
  status, first_seen, last_seen)
- Add ARP table collector for IP resolution and online detection
- Fix di_get_summary jsonfilter counting (use per-field extraction)
- Rename uci_get to di_ctl_get to avoid collision with OpenWrt's
  /lib/functions.sh which overwrites it
- Replace rx_bytes/tx_bytes/risk_score with first_seen/last_seen
  timeline in show command

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:10:12 +01:00
932c578dad fix(device-intel): Align Makefile with SDK build pattern
Add PKG_ARCH:=all, empty Build/Compile, conffiles section, and
consistent SECTION/CATEGORY/SUBMENU to match other secubox-app packages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:02:07 +01:00
57db9cfb40 feat: Add device-intel and dns-provider packages
Add 4 new packages implementing unified device intelligence and
DNS provider API management:

- secubox-app-dns-provider: dnsctl CLI with OVH, Gandi, Cloudflare
  adapters for DNS record CRUD, HAProxy vhost sync, propagation
  verification, and ACME DNS-01 wildcard certificate issuance
- luci-app-dns-provider: RPCD handler + LuCI views for provider
  settings and DNS record management
- secubox-app-device-intel: Aggregation layer merging mac-guardian,
  client-guardian, DHCP, P2P mesh, and exposure data with heuristic
  classification engine and USB/MQTT/Zigbee emulator modules
- luci-app-device-intel: RPCD handler + 5 LuCI views (dashboard,
  devices, emulators, mesh, settings) with shared API and CSS

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:47:20 +01:00
297917e79a feat(jellyfin): Add secubox-app-jellyfin and luci-app-jellyfin packages
Docker-based Jellyfin media server with UCI config (port, image, media
paths, GPU transcoding), procd init, jellyfinctl CLI, and LuCI frontend
with status/config/logs view.

Also adds Punk Exposure Engine architectural README documenting the
Peek/Poke/Emancipate service exposure model and DNS provider API
roadmap. CLAUDE.md updated with architectural directive.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:50:59 +01:00
c6de8b2b1b chore(exposure): Remove obsolete view files replaced by KISS redesign
Delete overview.js, tor.js, ssl.js — all functionality is now in the
single services.js view.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:27:46 +01:00
9def2ad15a fix(exposure): Fix toggle switches always showing as ON
Use DOM property assignment (cb.checked = value) instead of HTML
attribute ('checked': false) which browsers treat as checked since
any attribute presence means ON for boolean HTML attributes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:19:49 +01:00
4c8799d520 feat(exposure): KISS redesign with enriched service names and vhost integration
Collapse 4-tab UI into single-table view. Enrich scan with real names
from uhttpd UCI, streamlit UCI, docker containers, glances and Lyrion.
Add vhost_list RPCD method to show HAProxy domains and uhttpd instances.
Fix RPC expect unwrapping, trim CSS from 870 to 178 lines.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:15:04 +01:00
dc6a8f9c62 fix(streamlit): Auto-install requirements from ZIP uploads and support non-standard filenames
The install_requirements() function only matched requirements.txt exactly,
missing files like requirements_bazi.txt shipped in user ZIP uploads. Now
falls back to any requirements*.txt file. RPCD upload handlers (upload_zip,
upload_finalize) also trigger pip install inside the container at deploy time.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 12:31:02 +01:00
0083513cdc fix(streamlit): Add chunked upload to bypass uhttpd 64KB JSON limit and support top-level .py apps
uhttpd-mod-ubus silently rejects JSON-RPC requests >64KB with "Parse error",
causing uploads of .py files >48KB to fail with "No related RPC reply".

- Add chunked upload (upload_chunk + upload_finalize) that splits base64
  content into 40KB pieces sent sequentially, then reassembles server-side
- Frontend auto-selects chunked upload when content exceeds 40KB
- Stop polling during upload to prevent RPC batch conflicts
- RPCD handlers use cat-to-tempfile instead of shell variables for stdin
  to avoid BusyBox argument size limits
- Container startup script handles top-level .py files (not just subdirs)
- streamlitctl cmd_instance_start also handles top-level .py files
- Add upload_chunk and upload_finalize to ACL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 10:16:47 +01:00
8691a5e048 fix(streamlit): Fix btoa crash on UTF-8 .py file upload
Read all files as ArrayBuffer and use Uint8Array chunked encoding
for base64, replacing btoa(text) which throws DOMException on
non-ASCII characters (accents, CJK, etc).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 09:40:51 +01:00
db486a56ad fix(streamlit): Fix ZIP upload, app management and add rename support
- Fix ZIP upload: install unzip dependency, fix empty array check
  (jsonfilter returns "[ ]" not "[]"), redirect unzip stdout to
  prevent JSON corruption, use readAsArrayBuffer instead of
  deprecated readAsBinaryString, add .catch() error handler
- Fix list_apps to scan subdirectories for ZIP-uploaded apps,
  skip Streamlit pages/ convention dir, prefer app.py as entry point
- Fix set_active_app: replace broken streamlitctl call with direct
  UCI update
- Fix remove_app: replace broken streamlitctl call with direct
  file removal and UCI cleanup
- Fix add_app: replace broken streamlitctl call with direct UCI
- Add rename_app and rename_instance RPCD methods with ACL entries
- Activate now auto-creates an instance with next available port
- Apps list shows UCI display name separate from filesystem ID
- Sanitize uploaded filenames for UCI compatibility
- Add rename buttons and modals for apps and instances
- Add error notifications for failed deletes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 09:25:01 +01:00
f2b40efbfa fix(streamlit): Add missing RPCD ACL entries for Gitea and zip methods
Adds get_gitea_config, gitea_list_repos to read permissions and
save_gitea_config, gitea_clone, gitea_pull, preview_zip, upload_zip
to write permissions, fixing "Access denied" (-32002) errors.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 08:44:19 +01:00
daa4c48375 fix(localai): Add gte-small preset, fix RPC expect unwrapping and chat JSON escaping
- Add gte-small embedding model preset to localaictl with proper YAML
  config (embeddings: true, context_size: 512)
- Fix RPC expect declarations across api.js, dashboard.js, models.js to
  use empty expect objects, preserving full response including error fields
- Replace fragile sed/awk JSON escaping in RPCD chat and completion
  handlers with file I/O streaming through awk for robust handling of
  special characters in LLM responses
- Switch RPCD chat handler from curl to wget to avoid missing output
  file on timeout (curl doesn't create -o file on exit code 28)
- Bypass RPCD 30s script timeout for chat by calling LocalAI API
  directly from the browser via fetch()
- Add embeddings flag to models RPC and filter embedding models from
  chat view model selector

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 08:36:20 +01:00
28acb7e70f fix(localai): Fix health check and uptime detection in RPCD handler
Health check grep was case-sensitive ("ok") but LocalAI returns "OK".
Uptime detection fell into the lxc-info branch (command exists on router)
even though no localai container runs, causing uptime to always be 0.
Simplified to always use /proc/PID which works for both native and
containerized processes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 19:04:23 +01:00
02126aa7d3 feat(wireguard-dashboard): Persist server endpoints in UCI for reuse across views
Server endpoints were stored only in browser sessionStorage, lost on tab
close/refresh. Now endpoints are saved in a dedicated UCI config file
(wireguard_dashboard) with RPCD methods to manage them. The wizard
auto-saves the endpoint after tunnel creation, and peers/QR views use a
dropdown of saved endpoints instead of requiring manual re-entry.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:32:36 +01:00
2ed00d1967 fix(wireguard-dashboard): Fix RPC expect unwrapping, wizard interface naming and key persistence
- Change generateConfig/generateQR RPC declarations to use empty expect
  so error responses are not silently discarded by LuCI's RPC unwrapper
- Simplify handleShowQR to always check backend for stored key first
- Auto-detect next available interface name in wizard (wg1 if wg0 exists)
- Pass private key to addPeer in wizard's createPeers for QR persistence

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 17:35:44 +01:00
75e3f59207 fix(wireguard-dashboard): Bypass jshn for QR code output to avoid argument size limit
The base64-encoded SVG QR code exceeded jshn's argument list limit,
causing "Argument list too long" errors. Build the JSON response
manually via file I/O so the large string is never passed as a
command argument.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 16:57:53 +01:00
2ab0965917 feat(wireguard-dashboard): Persist peer private keys in UCI for QR code generation
Store the client private key in UCI config (_client_private_key) when a
peer is created, so QR codes and config files can be generated after
page refresh without prompting the user to manually re-enter the key.
Old peers without stored keys still get the manual entry fallback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 16:54:26 +01:00
2d810a2e95 feat(mac-guardian): Add DHCP lease protection for odhcpd
Prevent odhcpd crashes from MAC randomization causing hostname conflicts,
stale lease pile-up, and lease flooding. Adds hostname dedup, stale lease
cleanup, flood detection, CLI commands, RPC methods, and LuCI dashboard card.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 16:22:37 +01:00
373d77368e feat(mac-guardian): Rename to secubox-app-mac-guardian and add LuCI interface
Rename package folder to follow secubox-app-* convention and add
luci-app-mac-guardian with KISS dashboard: status cards, client table
with trust/block actions, recent alerts, and configuration form.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 16:06:48 +01:00
aeb4825b25 feat(mac-guardian): Add WiFi MAC security monitor
Pure-shell WiFi MAC address security monitor detecting randomized MACs,
OUI anomalies, MAC floods, and spoofing. Integrates with CrowdSec via
JSON log parsing and provides real-time hostapd hotplug detection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 15:26:18 +01:00
fa1f6ddbb8 feat(tor-shield): Add server mode for split-routing with public IP preservation
Server mode routes all outbound traffic through Tor while preserving
inbound connections (HAProxy, etc) on the public IP. Fixes kill switch
blocking response packets by adding ESTABLISHED,RELATED conntrack rule,
and adds PREROUTING chain for LAN client Tor routing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 13:46:26 +01:00
ea18674638 fix(security-threats): Remove null rendering in dashboard
LuCI's E() renders null array children as literal "null" text.
Use concat with empty arrays instead of ternary-to-null for
conditional peer/IOC table sections and top-level sections.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:51:50 +01:00
8c0f6a9b73 fix(security-threats): Detect mitmproxy running in LXC container
The process name is mitmweb (not mitmdump) when running inside the
mitmproxy LXC container. Use pgrep -f mitmweb for correct detection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:34:51 +01:00
c4302504df refactor(security-threats): KISS rewrite with mesh threat intelligence
Replace overengineered dashboard (2025 lines) with focused security
intelligence view (847 lines). Drop hero banner, risk gauge, device
zoning, nDPId correlation engine. Keep firewall stats, mitmproxy
threats, CrowdSec blocking. Add mesh intelligence section with P2P
threat-intel sharing (IOC counts, peer contributors, publish/apply).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:30:25 +01:00
1652b39137 feat(p2p): Add decentralized threat intelligence sharing via mesh
Share CrowdSec bans and mitmproxy detections between mesh nodes using
the existing blockchain chain + gossip sync. Received IOCs from trusted
peers are auto-applied as CrowdSec decisions based on a three-tier trust
model (direct/transitive/unknown).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:13:51 +01:00
857622ff56 feat(master-link): Add dynamic join IPK generation for mesh onboarding
Generate a minimal IPK on-the-fly when a client visits the master-link
landing page, so the "Download Package" step always works even without
a pre-built IPK bundle. The IPK configures the peer via postinst uci
commands (avoiding file conflicts with secubox-master-link), and can be
installed directly via opkg install URL from SSH.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 09:36:04 +01:00
3c1d6d2fd0 feat(lyrion): Add WAN access checkbox for firewall rules
Add wan_access UCI option and LuCI checkbox to optionally open Lyrion
ports (9000, 9090, 3483 TCP+UDP) on the WAN interface. WAN rules are
automatically removed when the option is disabled.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 08:06:54 +01:00
4797b7844d fix(lyrion): Add firewall rules and fix networking for device discovery
Open LAN firewall ports (TCP 9000/9090/3483, UDP 3483) on install and
service start so Squeezebox devices can discover and connect to Lyrion.
Fix LXC config to use host networking properly and add missing Docker
TCP 9090 CLI port mapping.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 08:00:09 +01:00
62f2f6a7a8 docs(secubox): Add KISS README for all 46 remaining packages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 07:34:06 +01:00
b516609bcc docs(master-link): Add README for both master-link packages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 07:16:22 +01:00
e74e44158f fix(master-link): Pre-read request file fields before cat truncation
Read timestamp, approved_at, and other fields into variables before
`cat > "$request_file"` truncates the file. Fixes invalid JSON output
(`"timestamp": ,`) in ml_join_approve, ml_join_reject, and
ml_promote_to_submaster.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:52:14 +01:00
13960d39c3 fix(master-link): Rename RPCD to luci.master_link and flatten JSON output
Hyphens in RPCD filenames break ubus CLI argument parsing. Rename
luci.master-link to luci.master_link and update all references in
the JS view, ACL, and Makefile. Also pipe RPCD method output through
tr -d '\n\t' so ubus receives single-line JSON it can parse.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:40:41 +01:00
c4c829a593 fix(master-link): Suppress p2p-mesh.sh stdout noise from sourced libraries
Use >/dev/null 2>&1 instead of just 2>/dev/null when sourcing
master-link.sh and calling chain_add_block, mesh_init, peer_add,
factory_trust_peer, and gossip_sync to prevent p2p-mesh.sh usage
text and block hashes from corrupting CGI JSON responses.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:38:11 +01:00
62c0850829 feat(master-link): Add secure mesh onboarding packages
Implement secubox-master-link (backend) and luci-app-master-link (LuCI
frontend) for secure node onboarding into the SecuBox mesh via
HMAC-SHA256 join tokens, blockchain-backed peer trust, and gigogne
(nested) hierarchy with depth limiting.

Backend provides: token management, join/approve/reject protocol, IPK
bundle serving, CGI API endpoints, and a dark-themed landing page for
new nodes. Frontend provides a 3-tab LuCI view (overview, join requests,
mesh tree) with RPCD integration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 06:15:47 +01:00
c0991336bb fix(mitmproxy): Fix JSON output corruption from grep -c exit codes
grep -c returns exit code 1 when no matches found (even though it
outputs 0), causing `|| echo 0` to append an extra 0 and corrupt
the JSON response. This broke ubus calls and LuCI status display.

Use `: ${var:=0}` pattern instead to provide defaults.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 05:15:27 +01:00
b2f0e23c32 fix(simplex): Use LXC configured path and skip existing rootfs download
- Read LXC path from /etc/lxc/lxc.conf instead of hardcoding /var/lib/lxc
  (OpenWrt uses /srv/lxc by default)
- Skip Alpine rootfs download if file already exists in /tmp

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 05:07:44 +01:00
c89e965631 fix(factory): Suppress ubus output to prevent JSON corruption in CGI responses
The factory_audit_log function's ubus call was only redirecting stderr,
allowing stdout JSON output to leak into CGI responses when Gitea backup
is enabled. This caused JSON parse errors in the Factory dashboard when
creating snapshots.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 04:17:48 +01:00
045af683b3 fix(feed): Remove stale mitmproxy r19 package
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 16:21:41 +01:00