Shipped work
Development
Apps and tools I've built and shipped, mostly for iOS. Direct links to the App Store below.
MistPulse
Network management for Juniper Mist & Aruba Central, built on their official APIs
MistPulse: Key Features
MistPulse is a network management app for Juniper Mist and HPE Aruba Networking New Central. It is built entirely on the vendors' official REST and WebSocket APIs: every screen reads live data from, and writes changes to, your organization through those APIs. There is no screen scraping and no agent to install on your network.
MistPulse Mobile (iOS)
API powered: connects to the Juniper Mist API (REST and WebSocket) and the Aruba New Central API. Your org API tokens are kept on MistPulse's secure backend, never on the phone, and every request goes through a proxy that only allows approved API endpoints.
Organizations and sites
- Multiple orgs from both vendors, added with an API token and cloud region, with one tap to switch between them.
- Sites dashboard with device and client counts, online and offline status, and search.
- Site SLE health (coverage, capacity, roaming, throughput, time to connect) with selectable time ranges and drill down into each metric.
- Site alerts, device events and interactive floorplans.
Devices and clients
- Access points, switches, gateways and Mist Edges, each with a detailed status view.
- Switch port overview, hardware inventory and org wide device inventory.
- Live client lists with signal strength, band, SSID and connected AP, plus a detail view for every client.
- Multi select actions on APs and switches, including bulk rename.
- Device restart and firmware upgrade.
Troubleshooting
- Ping, traceroute, cable test, ARP table, show route and bounce port.
- Interactive device Live Shell (CLI) and Packet Capture.
- Marvis insights and Marvis Minis synthetic tests.
- Aruba New Central insights, services, client and device diagnostics.
Configuration (applied through the API)
- WLANs, WLAN templates and RF templates.
- Network templates, including Port Profiles and Port Config rules for Juniper EX/QFX and Aruba CX switches, plus networks, RADIUS, syslog, routing policies and VRRP.
- Gateway templates: port config, BGP, OSPF, path preference, service policies, DHCP and extra routes; also hub profiles and VPNs.
- Site settings, site groups, device profiles and service policies.
- Security: NAC rules, NAC tags and NAC portals; IDP, antivirus and SecIntel profiles; WxLAN tags and rules.
- Access: PSKs and PSK portals, org admins, API tokens, webhooks and alarm templates.
- Aruba New Central advanced config: config profile assignment, MAC auth, webhooks, and device and org renaming.
Automations and alerts
- Push notifications for device up and down events, alarms and repeated NAC authentication failures.
- Scheduled daily or weekly health digests.
- Config drift detection for WLANs, templates and NAC rules.
- PSK lifecycle management, with expiry reminders and optional automatic revocation.
Siri and Shortcuts
- Ask Siri about offline APs, device status and health, site alerts, SLE scores, why an SLE score is low, low signal clients, port status and more.
Security and convenience
- Face ID, Touch ID or PIN app lock, with credentials held in the iOS Keychain.
- CSV export of lists for reporting.
- Crash monitoring for fast fixes.
MistPulse Web (mistpulse.jhurta.com)
API powered: the same Juniper Mist and Aruba New Central APIs as the mobile app, reached through MistPulse's secure proxy, which only allows approved API endpoints.
Guest mode, no account required
- Paste a Mist or Aruba New Central API token and org ID, choose the cloud region, and your network loads right away.
- Your credentials stay in that browser tab only: they are never saved to an account, and they disappear when you close the tab or end the session.
- Add multiple Mist and Aruba orgs to the same session and switch between them.
- Cloudflare Turnstile protects sign in from bots.
Full functionality in the browser
- The same sites, SLE health, alerts, devices, clients, floorplans and inventory views as the mobile app.
- Full configuration: WLANs, network, gateway and RF templates, Port Profiles and Port Config, NAC, PSKs, webhooks, alarm templates, org settings and Aruba config.
- Device actions: restart, firmware upgrade and bulk rename.
- Live Shell and Packet Capture, running directly in the browser.
- Aruba New Central ping and traceroute.
- An overview of the automations (alerts, health digests, drift detection and PSK lifecycle) that MistPulse runs for connected orgs.
Built for the desktop
- A responsive layout with a sidebar for large screens that also works on tablets and phones.
Mobile app only: push notifications, Face ID, Touch ID or PIN lock, Siri, and the Mist diagnostics that return their results over a live connection browsers can't open (ping, traceroute, cable test, ARP table, show route and bounce port).
Junificator
Translates Cisco, Meraki, Palo Alto, FortiGate, Arista & Ruckus configs into Junos and Mist, stateless and guest only
Config translation, not config generation
Junificator is a stateless, guest only web app that translates network device configurations from third party vendors into Juniper formats: Junos CLI, Mist JSON templates, or SRX/MX CLI, so an operator can review the result and push it, or a Juniper equivalent, into production with confidence.
No source config, credential, or generated output is ever persisted server side or in browser storage. Everything lives only for the life of a single translate request or a single browser tab.
Supported translation pairs
| Source | Targets |
|---|---|
| Cisco IOS, switch | Junos EX/QFX CLI; Mist switch template JSON |
| Cisco Meraki, switch | Junos EX/QFX CLI; Mist switch template JSON |
| Cisco Meraki MX, firewall | Junos SRX CLI; Mist Gateway template JSON |
| Cisco Meraki, routing, L3 SVIs | Junos MX CLI; Junos EX/QFX CLI; Mist switch template JSON |
| Cisco Meraki, wireless, SSIDs | Mist WLAN template JSON |
| Cisco Router, IOS/IOS XE | Junos MX CLI |
| Cisco ASA, firewall | Junos SRX CLI; Mist Gateway template JSON |
| Palo Alto, PAN OS firewall | Junos SRX CLI; Mist Gateway template JSON |
| Fortinet FortiGate, firewall | Junos SRX CLI; Mist Gateway template JSON |
| Arista EOS, switch | Junos EX/QFX CLI; Mist switch template JSON |
| Arista Router, EOS, L3 | Junos MX CLI |
| Ruckus standalone AP | Mist WLAN template JSON |
| Ruckus Controller, SmartZone, vSZ, ZoneDirector | Mist WLAN template JSON |
Only the pairs above are ever attempted. There is no format auto detection and no best effort translation between domains that do not share a data model; a switch config, for instance, is never sent through the firewall translator.
Deterministic by design, never AI
One parser turns vendor source text or JSON into a shared intermediate model, and one generator turns that model into the target output, selected purely by the source and target pair. Four intermediate data models, each scoped to one config domain so a translation only ever crosses formats that actually share meaning: switching (ports, VLANs, trunk/access mode, STP, LLDP), security and firewall (zones, address objects, rules, NAT), routing (L3 interfaces, static routes, OSPF, BGP, VRFs), and wireless (SSIDs, authentication and encryption, VLANs, isolation, RF bands, guest portal).
There is no AI or LLM anywhere in the translation path. Every mapping is deterministic, regex and schema driven code, so the same input always produces the same output, and every unmapped construct is explicitly reported, never guessed.
Warn, never fabricate
Any source construct with no faithful Juniper or Mist equivalent, such as Arista MLAG, an identity PSK WLAN, or an unrecognized OSPF network, is surfaced as an explicit warning telling the operator what to configure manually. It is never silently dropped and never approximated with plausible but wrong output.
Password and secret hashes (Cisco or Arista secret lines, device admin logins) are recognized and warned about, never translated, since hash formats aren't portable between vendors. A WLAN's own plaintext PSK is translated, since that's the same passphrase an admin would type directly into the target platform.
Interface name mapping is data driven, and VRF aware routing maps a static route in the device's own management VRF to Junos's dedicated management routing instance, while a route in any other VRF is flagged for manual placement rather than guessed. LACP and aggregated Ethernet bundling, named VLANs with SVI binding, and BGP (peer groups, neighbors, and network statements via a Junos export policy and prefix list) are all translated where the source data supports it.
Translate, validate, review, push
- Translate: source text or JSON comes in, target CLI or JSON goes out, along with a list of warnings.
- Validate: the output is checked for structural correctness (well formed set/delete lines for CLI targets, schema shaped JSON for Mist targets) before it's ever offered for push. Validation errors block the push, and warnings require the operator to explicitly acknowledge them first.
- Review: the operator reviews the output and every warning in the interface.
- Download or push: download the translated config as a file, or push Mist targeted output directly to the Mist Portal via the Mist API, using a Mist API token and org or site scope supplied for that one request only, never stored.
Input and security
Source configs can be pasted directly, or pulled live from Cisco Meraki's API (switch, firewall, routing, and wireless scopes) using a user supplied API key that's used only for that request.
All generated CLI output is sanitized against injection: embedded whitespace or newlines in any source derived field (descriptions, hostnames, route prefixes, BGP fields, OSPF area/network values) are neutralized before being interpolated into set/delete lines, so a malicious source config can't smuggle extra CLI statements into the output. JSON targeted output is built via structured serialization, which is inherently safe against the same class of injection.
Request size is capped, and debug/introspection endpoints (interactive docs, redoc, OpenAPI schema) are disabled in the deployed application. Nothing is written to disk, a database, or browser storage; the app is fully stateless and guest only.