Compare commits
2 Commits
8369e7fae5
...
7bd2bb544a
| Author | SHA1 | Date | |
|---|---|---|---|
| 7bd2bb544a | |||
| 83e8e4498c |
@@ -248,6 +248,7 @@ Vault structure: `infrastructure/`, `clients/`, `services/`, `projects/`, `msp-t
|
|||||||
| `/create-spec` | Create app specification for AutoCoder |
|
| `/create-spec` | Create app specification for AutoCoder |
|
||||||
| `/frontend-design` | Modern frontend design (auto-invoke after UI changes) |
|
| `/frontend-design` | Modern frontend design (auto-invoke after UI changes) |
|
||||||
| `/remediation-tool` | M365 breach checks, tenant sweeps, gated remediation |
|
| `/remediation-tool` | M365 breach checks, tenant sweeps, gated remediation |
|
||||||
|
| `/feature-request` | Howard submits a GuruRMM feature request — Claude classifies it and messages Mike |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
99
.claude/commands/feature-request.md
Normal file
99
.claude/commands/feature-request.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
Howard is submitting a GuruRMM feature request. Follow these steps exactly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1 — Read context
|
||||||
|
|
||||||
|
Read `.claude/identity.json` to get the machine hostname (for session ID and Ollama endpoint).
|
||||||
|
|
||||||
|
Read `projects/msp-tools/guru-rmm/docs/FEATURE_ROADMAP.md`. Extract the top-level section headers
|
||||||
|
and a representative sample of subsections so you understand the existing structure.
|
||||||
|
Do NOT print the roadmap to the user.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2 — Classify the feature using Ollama
|
||||||
|
|
||||||
|
The feature request is: $ARGUMENTS
|
||||||
|
|
||||||
|
Determine the Ollama endpoint:
|
||||||
|
- If hostname is `DESKTOP-0O8A1RL`: use `http://localhost:11434`
|
||||||
|
- All other machines (including Howard's): use `http://100.92.127.64:11434`
|
||||||
|
|
||||||
|
Call Ollama with model `qwen3:14b` to classify the request. Ask it to return:
|
||||||
|
1. Which top-level roadmap section this belongs in (e.g., "Core Agent Features", "Server/API Features",
|
||||||
|
"Dashboard & UI", "Platform & Infrastructure", "Integrations", "Future Considerations")
|
||||||
|
2. Suggested subsection — match an existing one if it fits; propose a new name if it doesn't
|
||||||
|
3. Suggested priority (P1 = critical/blocking, P2 = important/near-term, P3 = nice-to-have)
|
||||||
|
4. A 2-3 sentence plain-English summary of what Howard is asking for
|
||||||
|
|
||||||
|
Use this prompt structure for the Ollama call:
|
||||||
|
```
|
||||||
|
You are helping classify a feature request for GuruRMM, a Remote Monitoring & Management tool
|
||||||
|
for MSPs. The roadmap sections are: Core Agent Features, Server/API Features, Dashboard & UI,
|
||||||
|
Platform & Infrastructure, Integrations, Future Considerations.
|
||||||
|
|
||||||
|
Feature request: <$ARGUMENTS>
|
||||||
|
|
||||||
|
Respond with JSON only: {"section": "...", "subsection": "...", "priority": "P1|P2|P3", "summary": "..."}
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse the JSON response. If Ollama is unreachable, perform the classification yourself directly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3 — Send coord message to Mike
|
||||||
|
|
||||||
|
Post a message to the coord API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST http://172.16.3.30:8001/api/coord/messages \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"from_session": "<HOSTNAME>/claude-main",
|
||||||
|
"to_session": "DESKTOP-0O8A1RL/claude-main",
|
||||||
|
"project_key": "gururmm",
|
||||||
|
"subject": "Feature Request from Howard: <brief title>",
|
||||||
|
"body": "<full body — see format below>"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `<HOSTNAME>` comes from identity.json.
|
||||||
|
|
||||||
|
**Message body format:**
|
||||||
|
```
|
||||||
|
Howard submitted a feature request for GuruRMM.
|
||||||
|
|
||||||
|
FEATURE REQUEST
|
||||||
|
===============
|
||||||
|
<$ARGUMENTS verbatim>
|
||||||
|
|
||||||
|
PROPOSED PLACEMENT
|
||||||
|
==================
|
||||||
|
Section: <section from Ollama>
|
||||||
|
Subsection: <subsection from Ollama>
|
||||||
|
Priority: <P1/P2/P3>
|
||||||
|
|
||||||
|
SUMMARY
|
||||||
|
=======
|
||||||
|
<2-3 sentence summary from Ollama>
|
||||||
|
|
||||||
|
---
|
||||||
|
Submitted via /feature-request from <HOSTNAME> at <timestamp>
|
||||||
|
```
|
||||||
|
|
||||||
|
Send to `to_session: "DESKTOP-0O8A1RL/claude-main"` and also to `"Mikes-MacBook-Air/claude-main"`
|
||||||
|
so Mike sees it regardless of which machine he's on.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4 — Acknowledge to Howard
|
||||||
|
|
||||||
|
Tell Howard:
|
||||||
|
|
||||||
|
- His request was submitted to Mike
|
||||||
|
- Where you've suggested it fits in the roadmap (section + subsection)
|
||||||
|
- Suggested priority
|
||||||
|
- That Mike will review and decide if/how/when to build it
|
||||||
|
|
||||||
|
Keep it brief — one short paragraph. Do NOT say "I" did anything — say the request was sent.
|
||||||
75
tmp_roadmap_patch.py
Normal file
75
tmp_roadmap_patch.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
new_section = """
|
||||||
|
### Asset Location Tracking
|
||||||
|
MSP clients frequently ask "can you find this device if it's stolen?" — this feature makes the answer yes.
|
||||||
|
Primary use case is theft recovery and asset accountability, not real-time surveillance.
|
||||||
|
|
||||||
|
#### Approach by device type
|
||||||
|
|
||||||
|
**Laptops & desktops (Windows/macOS/Linux) — agent-based, no MDM required:**
|
||||||
|
Location is derived from visible WiFi networks (SSID + BSSID) sent to the Google or Microsoft
|
||||||
|
Geolocation API, which returns coordinates accurate to ~50-100m. Falls back to IP geolocation
|
||||||
|
(city-level) on wired-only or WiFi-disabled machines. No GPS hardware required.
|
||||||
|
|
||||||
|
**Phones & tablets — mobile agent app:**
|
||||||
|
A lightweight GuruRMM Agent app (iOS App Store / Google Play) reports background location and
|
||||||
|
can receive remote lock commands via standard APNs/FCM push — no Apple MDM vendor certificate
|
||||||
|
required. This covers the "find my stolen iPad" use case without the full MDM enrollment stack.
|
||||||
|
|
||||||
|
#### Agent (Windows/macOS/Linux)
|
||||||
|
- [ ] Collect visible WiFi networks (SSID, BSSID, signal strength) - P2
|
||||||
|
- [ ] Send to geolocation API (Google or Microsoft, configurable); store lat/lng + accuracy radius - P2
|
||||||
|
- [ ] IP geolocation fallback when WiFi scan returns empty - P2
|
||||||
|
- [ ] Location reported on each inventory checkin (not continuous polling) - P2
|
||||||
|
- [ ] Policy flag: location collection enabled/disabled per site or agent - P2
|
||||||
|
- [ ] On-demand location request (server pushes LocationRequest, agent responds immediately) - P2
|
||||||
|
- [ ] Platform WiFi scan implementations:
|
||||||
|
- [ ] Windows: `netsh wlan show networks mode=bssid` or `wlanapi` - P2
|
||||||
|
- [ ] macOS: CoreWLAN CWInterface.scanForNetworks - P2
|
||||||
|
- [ ] Linux: `iwlist scan` / nl80211 via netlink - P2
|
||||||
|
- [ ] Agent platform parity: all three platforms in same release per parity rule - P1
|
||||||
|
|
||||||
|
#### Server
|
||||||
|
- [ ] `agent_locations` table (agent_id, recorded_at, lat, lng, accuracy_meters, source: wifi|ip|gps, raw_wifi_scan JSON) - P2
|
||||||
|
- [ ] Location history — retain last N readings (configurable, default 30 days) - P2
|
||||||
|
- [ ] `POST /api/agents/:id/location` ingest endpoint - P2
|
||||||
|
- [ ] `GET /api/agents/:id/location` — current + history - P2
|
||||||
|
- [ ] `POST /api/agents/:id/location/request` — on-demand location pull - P2
|
||||||
|
- [ ] Fleet location endpoint: `GET /api/sites/:id/locations` (all agents for a site) - P2
|
||||||
|
|
||||||
|
#### Dashboard
|
||||||
|
- [ ] Location tab on Agent Detail page — map embed (Leaflet.js, OpenStreetMap tiles, no API key) with accuracy circle - P2
|
||||||
|
- [ ] Last known location + timestamp in Agent Overview card - P2
|
||||||
|
- [ ] Fleet map view — all online agents for a site pinned on one map - P3
|
||||||
|
- [ ] Location history timeline (scroll through past readings) - P3
|
||||||
|
- [ ] "Request Location Now" button — fires on-demand poll, updates map live - P2
|
||||||
|
- [ ] Geofence alerts — notify if agent appears outside defined boundary - P3
|
||||||
|
|
||||||
|
#### Mobile App (iOS + Android) — future phase
|
||||||
|
- [ ] Lightweight GuruRMM Agent app distributed via App Store / Google Play - P3
|
||||||
|
- [ ] Background location reporting (uses standard OS location APIs, not MDM) - P3
|
||||||
|
- [ ] Remote lock via APNs/FCM push notification (guided access on iOS, device admin on Android) - P3
|
||||||
|
- [ ] Enrollment via QR code / enrollment URL (same server, mobile-specific agent type) - P3
|
||||||
|
- [ ] No Apple MDM vendor certificate required — standard app distribution - P3
|
||||||
|
|
||||||
|
#### Out of scope (v1)
|
||||||
|
- Real-time continuous GPS tracking (battery/privacy concerns; on-demand + checkin is sufficient)
|
||||||
|
- Full MDM profile management for iOS/Android (separate MDM integration feature if ever needed)
|
||||||
|
- Wired-only machines where WiFi is disabled and IP geolocation accuracy is unacceptable
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open('/home/guru/gururmm/docs/FEATURE_ROADMAP.md', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Insert before the --- that separates Core Agent Features from Server/API Features
|
||||||
|
# That separator comes right after the tray security section ending at line ~183
|
||||||
|
marker = "- [ ] Optional PIN/password for sensitive actions - P3\n\n---\n\n## Server/API Features"
|
||||||
|
replacement = "- [ ] Optional PIN/password for sensitive actions - P3\n" + new_section + "\n---\n\n## Server/API Features"
|
||||||
|
|
||||||
|
if marker in content:
|
||||||
|
content = content.replace(marker, replacement, 1)
|
||||||
|
with open('/home/guru/gururmm/docs/FEATURE_ROADMAP.md', 'w') as f:
|
||||||
|
f.write(content)
|
||||||
|
print("inserted")
|
||||||
|
else:
|
||||||
|
print("MARKER NOT FOUND")
|
||||||
Reference in New Issue
Block a user