@@ -351,7 +351,7 @@ The example is useful for demonstrating the relationship views, but it should no
351351| Simplified parser | Good for common UCI files, not a complete UCI interpreter |
352352| Simplified decision engine | Useful for visual exploration, not a full firewall simulation |
353353| Protocol and port fields are not evaluated | Per-service conclusions may be inaccurate |
354- | Browser-local persistence | Saved state is per browser/profile and is not portable without a future import/export feature |
354+ | Browser-local persistence | Saved state is per browser/profile unless exported as JSON |
355355| CDN dependency | Graph rendering depends on external script availability |
356356| No automated tests | Behaviour is currently verified manually |
357357
@@ -373,8 +373,9 @@ Stored fields:
373373
374374Relevant functions:
375375
376- - ` saveToLocalStorage() ` .
377- - ` loadFromLocalStorage() ` .
376+ - ` saveState() ` .
377+ - ` loadState() ` .
378+ - ` clearExpiredState() ` .
378379- ` readStoredState() ` .
379380- ` normaliseSavedDevices() ` .
380381- ` normaliseSavedTestPath() ` .
@@ -415,13 +416,13 @@ Relevant functions and elements:
415416- ` #currentYear ` .
416417- ` setCurrentYear() ` .
417418
418- ## Future Enhancements
419+ ## Implemented Future Enhancements
419420
420- The following planned phases continue the roadmap sequence after implemented Phase A-C.
421+ The following phases continue the roadmap sequence after Phase A-C and are now implemented in ` public/index.html ` .
421422
422423### Phase D: Local Storage Lifecycle Management
423424
424- Status: planned .
425+ Status: implemented .
425426
426427Objective: prevent stale browser state from living indefinitely while keeping the local-first workflow.
427428
@@ -434,19 +435,18 @@ Requirements:
434435- Handle corrupted ` localStorage ` data gracefully.
435436- Preserve backwards compatibility where possible for existing saved payloads.
436437
437- Implementation notes :
438+ Implemented details :
438439
439- - Keep ` STORAGE_KEY ` as the stable state namespace.
440- - Introduce ` STORAGE_TTL_DAYS = 45 ` .
441- - Store ` savedAt ` or equivalent metadata in the persisted payload.
442- - Implement ` saveState() ` .
443- - Implement ` loadState() ` .
444- - Implement ` clearExpiredState() ` .
445- - Call ` clearExpiredState() ` during startup before applying saved state.
440+ - ` STORAGE_KEY ` remains the stable state namespace.
441+ - ` STORAGE_TTL_DAYS = 45 ` defines expiry.
442+ - ` savedAt ` is stored in the persisted payload.
443+ - ` saveState() ` writes the timestamped state.
444+ - ` loadState() ` restores state and falls back to defaults.
445+ - ` clearExpiredState() ` silently removes expired or corrupted payloads on startup.
446446
447447### Phase E: Graph Initial State Improvements
448448
449- Status: planned .
449+ Status: implemented .
450450
451451Objective: improve first-load user experience by preventing automatic path highlighting.
452452
@@ -458,15 +458,16 @@ Requirements:
458458- No path should be highlighted until the user explicitly clicks a graph node.
459459- No path should be highlighted until the user explicitly clicks a relationship entry.
460460
461- Implementation notes :
461+ Implemented details :
462462
463- - Separate path-result rendering from graph path highlighting.
464- - Track whether the user has explicitly requested a path highlight.
465- - Keep automatic path re-evaluation for text results, but defer graph highlighting until user action.
463+ - Path-result rendering is separated from graph path highlighting.
464+ - ` graphPathHighlightRequested ` tracks explicit path-highlighting intent.
465+ - Automatic re-renders update text results without selecting graph elements.
466+ - Graph highlighting is triggered only by "Test Path", graph node clicks, or relationship-card clicks.
466467
467468### Phase F: Bulk Host Import
468469
469- Status: planned .
470+ Status: implemented .
470471
471472Objective: allow users to populate devices from existing network inventories instead of manually adding hosts one at a time.
472473
@@ -503,13 +504,13 @@ Supported Linux neighbour table format:
503504172.16.20.11 dev br-iot lladdr aa:bb:cc:dd:ee:00 STALE
504505```
505506
506- Implementation notes :
507+ Implemented details :
507508
508- - Create ` importBulkHosts() ` .
509- - Create ` parseBulkHosts() ` .
510- - Create ` parseHostLine() ` .
511- - Create ` mergeDevices() ` .
512- - Report skipped or unrecognised lines without blocking valid imports .
509+ - ` importBulkHosts() ` imports the textarea content .
510+ - ` parseBulkHosts() ` parses host data line-by-line .
511+ - ` parseHostLine() ` handles host-list, neighbour/ARP, and DHCP lease formats .
512+ - ` mergeDevices() ` merges by IP without overwriting manually supplied names or zones .
513+ - Skipped and unresolved lines are reported in the import result panel .
513514
514515Benefits:
515516
@@ -519,7 +520,7 @@ Benefits:
519520
520521### Phase G: Zone Inference Engine
521522
522- Status: planned .
523+ Status: partially implemented .
523524
524525Objective: automatically assign firewall zones from subnet definitions when imported hosts do not include a zone.
525526
@@ -551,16 +552,25 @@ Expected inferred result:
551552zone = iot
552553```
553554
554- Implementation notes :
555+ Implemented details :
555556
556- - Add a subnet mapping input area.
557- - Parse CIDR notation into comparable network ranges.
558- - Apply inference during bulk import and device normalisation.
559- - Surface unresolved hosts so the user can assign zones manually.
557+ - The ` subnetMappings ` textarea stores subnet-to-zone mappings.
558+ - ` parseSubnetMappings() ` parses CIDR mappings.
559+ - ` inferZoneForIp() ` assigns zones during import when a host line has no explicit zone.
560+ - Unresolved imported hosts are counted in the import result panel.
561+
562+ Todo:
563+
564+ - Supported Input Formats
565+ - 1 . Manual Zone/Subnet Mapping (done)
566+ - 2 . OpenWRT UCI Export (todo)
567+ - uci show firewall | grep "\. network="
568+ - uci show network | grep -E "\. (ipaddr|netmask|proto)="
569+ -
560570
561571### Phase H: Network Discovery Importers
562572
563- Status: planned .
573+ Status: partially implemented .
564574
565575Objective: support importing host data directly from common network tooling output.
566576
@@ -571,16 +581,28 @@ Initial import targets:
571581- OpenWrt ` ip neighbour ` .
572582- OpenWrt ` cat /tmp/dhcp.leases ` , preferably because it includes hostnames.
573583
574- Implementation notes:
584+ Implemented details:
585+
586+ - ` parseNeighbourLine() ` supports Linux/OpenWrt ` ip neighbour ` and common ` arp -a ` output.
587+ - ` parseDhcpLeaseLine() ` supports OpenWrt ` /tmp/dhcp.leases ` .
588+ - DHCP hostnames are preferred when present.
589+ - IP-only names are used when no hostname is available.
590+ - Skipped source lines are shown in the import result panel.
575591
576- - Feed parsed importer output into the Phase F bulk host import path.
577- - Prefer hostnames from DHCP lease data when available.
578- - Fall back to IP-only device names when no hostname is present.
579- - Preserve raw importer output for troubleshooting skipped lines.
592+ TODO:
593+
594+ - Better placeholder for different import methods
595+ - Support for ` openwrt_export_hosts.sh ` script
596+ - ip,hostname,zone,mac
597+ 172.16.20.10,Alexa-Kitchen,iot,aa:bb:cc:dd:ee: ff
598+ 172.16.20.11,Alexa-Bedroom,iot,aa:bb:cc:dd:ee:00
599+ 172.16.30.25,Guest-Phone,guest,aa:bb:cc:dd:ee:11
600+ - ? button which points to the script
601+ -
580602
581603### Phase I: Relationship Analysis Engine
582604
583- Status: planned .
605+ Status: implemented .
584606
585607Objective: move beyond visualisation and provide automated security analysis.
586608
@@ -595,41 +617,47 @@ Requirements:
595617- Detect zones with unrestricted forwarding.
596618- Detect device exceptions that bypass segmentation.
597619
598- Implementation notes :
620+ Implemented details :
599621
600- - Build analysis rules on top of ` evaluateZonePath() ` and ` evaluateDevicePath() ` .
601- - Return findings with severity, affected source, affected destination , and reason.
602- - Add a findings panel before recommending changes .
622+ - ` buildAnalysisFindings() ` builds findings on top of ` evaluateZonePath() ` and ` evaluateDevicePath() ` .
623+ - Findings include severity, title , and reason.
624+ - ` renderAnalysisFindings() ` renders the findings panel.
603625
604626### Phase J: Rule Engine Accuracy
605627
606- Status: planned .
628+ Status: implemented .
607629
608- Improve decision accuracy before adding policy recommendations.
630+ Decision accuracy has been improved before adding policy recommendations.
609631
610- Candidate improvements:
632+ Implemented improvements:
611633
612634- Honour protocol matching.
613635- Honour destination port matching.
614636- Represent rule order more explicitly in explanations.
615637- Distinguish ` ACCEPT ` , ` REJECT ` , and ` DROP ` .
616638- Surface unsupported rule fields in the UI.
617- - Consider zone ` input ` and ` output ` policies where relevant .
639+ - Keep zone ` input ` and ` output ` visible in zone cards while forwarding decisions remain based on zone forwardings and same-zone forward policy .
618640
619641### Phase K: Import, Export, And Comparison
620642
621- Status: planned .
643+ Status: Mostly .
622644
623- Add workflows for longer-lived analysis.
645+ Workflows for longer-lived analysis are now available .
624646
625- Candidate improvements:
647+ Implemented improvements:
626648
627649- Export device mappings as JSON or CSV.
628650- Import saved device mappings.
629651- Export graph images.
630652- Compare two firewall configs.
631653- Show before/after impact for changed forwardings and rules.
632654
655+ Todo:
656+
657+ - Clear colour coding for Export Session
658+ - Clearer button for Import Session
659+
660+
633661## Development Notes
634662
635663The current implementation is intentionally simple:
0 commit comments