diff --git a/CLAUDE.md b/CLAUDE.md index ee46429..fdf8301 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,15 +12,12 @@ is the engineering counterpart. ## 1. What this app does -Electron desktop client for operating a **Ciena MCMS 6.2** PON Manager -fleet. Top-level **tabs** (Dashboard / ONU / OLT) switch between: +Electron desktop client for two bulk operations against **Ciena +MCMS 6.2** PON Manager: -- **Dashboard** — read-only network telemetry (see §15). -- **ONU** — two sub-tabs: an **Info / stats** page (per-ONU optical/FEC plus - the CPE router's DHCPv4/v6 lease health, §17) and the **Fleet & upgrade** - flow (the original purpose: bulk ONU firmware upgrades + verify). -- **OLT** — bulk OLT NNI-service edits: PON flooding mode (private↔auto) and - DHCPv4/v6 filter (pass↔umt), see §14. +1. **Bulk ONU firmware upgrades** (the original purpose). +2. **Bulk OLT PON flooding-mode changes** (private↔auto on NNI services — + see §14). Reference deployment: GNXS / Tibit MicroPlug ONUs running Interos Everest (EV051xxR / EV052xxR firmware family) behind Tibit OLTs. @@ -119,16 +116,12 @@ stream progress events back to the renderer. | `api:listFleet` | ONU-CFG + ONU-STATE + OLT-STATE merged | — | | `api:fetchStates` | per-ONU state fallback if bulk failed | `states:progress` | | `api:listOnuConfigs` / `api:getOnuConfig` | direct CFG access | — | -| `api:getOnuCpe` | CPE (router) DHCP lease health + OUI vendor | — | -| `api:getOnuDetail` | rich ONU detail: firmware/UNI/alarms/OLT/switch/traffic/CPE | — | -| `api:getOltDetail` | OLT detail: traffic/temp/ONU-counts/laser/alarms/switch | — | | `api:listOnuFirmware` / `api:uploadFirmware` | firmware inventory | — | | `api:planUpgrade` | dry-run plan for selected ONUs | — | | `api:executePerOnu` | Procedure 7 — per-ONU PUTs | `upgrade:progress` | | `api:executeBulkTask` | Procedure 8 — single AUTO-TASK-CFG | — | | `api:getTaskConfig` / `api:getUpgradeStatus` | poll helpers | — | | `api:deleteOnus` | bulk delete (CFG + best-effort STATE) | `delete:progress` | -| `api:dashboardStats` | network telemetry aggregates (Dashboard tab) | — | | `api:listOlts` | OLT-CFG list + per-OLT NNI flood-mode summary | — | | `api:executeFloodChange` | bulk PON flooding-mode flip (GET→plan→PUT) | `olt-flood:progress` | | `api:fetchFecHealth` | pre-flight FEC pre/post + optical | `fec:progress` | @@ -143,10 +136,8 @@ stream progress events back to the renderer. ### Fleet view -- Login with email / password. TLS to MCMS is always verified - (`rejectUnauthorized: true`); there is no accept-self-signed option — - MCMS must present a valid certificate. The web server can prefill the host - field from `PFW_MCMS_URL`. +- Login with email / password, accept-self-signed-TLS toggle (essential + for lab MCMS installs). - Bulk fleet load: `listAllOnuConfigs` + `listAllOnuStates` + `listAllOltStates`, all paginated via the `next` cursor at page size 100 (see §5). @@ -359,12 +350,8 @@ state_collection.STATS["OLT-PON"]["RX Post-FEC BER"] → The pre-flight fetch (`api:fetchFecHealth`) and the verify fetch (`api:fetchOnuSnapshot`) both call `getOnuState(id)` and extract via -`extractOnuHealth`. For *current* FEC/optical, prefer ONU-STATE. - -The time-series endpoint **is** used, but only for the ONU detail page's -traffic sparkline (`getOnuStatsSeries` → `api:getOnuDetail`, §17): it pulls -the last ~hour of samples for the down/up rate history. Don't use it for the -live FEC pill — that stays on ONU-STATE. +`extractOnuHealth`. The time-series stats endpoint is **not used** +anywhere — earlier code that hit it has been removed. `extractOnuHealth` accepts both shapes: the bare state doc (`{STATS: ...}`) and the UI-helper wrapped form @@ -666,54 +653,48 @@ Key procedure citations: --- -## 14. OLT NNI-service edits (bulk flood mode + DHCP filter) +## 14. OLT PON flooding mode (bulk private↔auto) Second bulk feature, added after the firmware upgrader. Lets an operator -edit OLT NNI services across many OLTs at once. Two concerns, applied -together in one GET→edit→PUT per OLT: +flip the PON flooding mode of OLT NNI services across many OLTs at once. -### The two mutation rules +### The mutation rule (the whole feature in one fact) -Both live on each `OLT-CFG["NNI Networks"][i]` entry, both confirmed -empirically from operator paste-backs of `s0.c76.c0`: +On Tibit OLTs, a service's flooding mode is encoded by the **presence or +absence of one key** on its `OLT-CFG["NNI Networks"][i]` entry: -1. **Flooding mode** — the **presence/absence of the `PON FLOOD ID` key**: - present (any value, incl. `0`) → **private**; absent → **auto**. So - private→auto is `delete entry['PON FLOOD ID']`; auto→private is - `entry['PON FLOOD ID'] = 0`. -2. **DHCP filter mode** — a **value** under the nested `Filter` object: - `entry.Filter.DHCPv4` / `entry.Filter.DHCPv6`, e.g. `"pass"` ↔ `"umt"` - (siblings `EAPOL`/`PPPoE`/`NDP` are left alone). Value replacement, not - key presence. **Replace-only-when-present**: an entry with no `Filter` - (or no such key) is skipped, never invented. +- **`PON FLOOD ID` key present** (any value, including `0`) → **private** +- **`PON FLOOD ID` key absent** → **auto** -Everything else on the entry and the rest of the OLT-CFG is preserved. -Default actions: TAG MATCH `s0.c76.c0`, flood `private→auto`, DHCPv4/v6 -`pass→umt`. All directions are wired, so changes roll back from the same UI. +So private→auto is `delete entry['PON FLOOD ID']`; auto→private is +`entry['PON FLOOD ID'] = 0`. Everything else on the entry (`TAG MATCH`, +`Learning Limit`, …) and the rest of the OLT-CFG is preserved. This was +confirmed empirically by diffing two paste-backs of the same OLT +(`24:65:e1:cc:af:1e`, NNI `s0.c76.c0`) in private vs auto — the *only* +difference was that key. + +The default action ships as: TAG MATCH = `s0.c76.c0`, mode `private` → +`auto`. Both directions are wired so a change can be rolled back from the +same UI. ### Data flow ``` listOlts ─► McmsClient.listAllOltConfigs ─► summarizeOltNniNetworks (pure) -executeFloodChange ─► per-OLT: getOltConfig ─► planNniEdit (pure, no-mutate) - (channel name kept for wire compat) ─► putOltConfig (full-doc PUT) +executeFloodChange ─► per-OLT: getOltConfig ─► planFloodChange (pure, no-mutate) + ─► putOltConfig (full-doc PUT) ``` -- **Pure helpers** at the bottom of `src/mcms-api.js`: `floodModeOfNni`, - `dhcpModeOfNni`, `summarizeOltNniNetworks`, `tagPatternToRegex`, - `planNniEdit`. `planNniEdit(oltCfg, { tagPattern, flood, dhcpv4, dhcpv6 })` - clones the `NNI Networks` array (and any edited `Filter`) and never mutates - its input. Returns `{ newDoc, changes, unchanged }`, where a change is - `{ index, tagMatch, edits: [{ type, from, to }] }` — `type` is `'flood'`, - `'DHCPv4'`, or `'DHCPv6'`, so one entry can carry several edits. -- Each concern is optional (`flood`/`dhcpv4`/`dhcpv6` may be `null`); the UI - has three independent action dropdowns. +- **Pure helpers** live at the bottom of `src/mcms-api.js`: + `floodModeOfNni`, `summarizeOltNniNetworks`, `tagPatternToRegex`, + `planFloodChange`. `planFloodChange` clones the `NNI Networks` array and + never mutates its input — it returns `{ newDoc, changes, unchanged }`. - **TAG MATCH pattern** supports exact strings, `*`/`""` (match all), and `*` globs (e.g. `s0.c76.*`). `tagPatternToRegex` escapes regex metachars then turns `*` into `.*`. -- **`from` guards**: only entries currently on the `from` mode/value are - flipped; entries already at target are left in `unchanged` (the per-OLT - `noop` case), so re-running is idempotent. +- **`fromMode` guard**: only entries currently in `fromMode` are flipped; + entries already in the target mode are recorded in `unchanged` (the + per-OLT `noop` case), so re-running is idempotent. - **Concurrency 3** on the write path (vs 5 for ONU delete, 8 for state fetch) — OLT writes carry far more blast radius. - **PUT-as-replace**, same gotcha as ONU-CFG (§5.7): the handler GETs the @@ -740,197 +721,4 @@ entries pass through untouched. --- -## 15. Tabbed navigation & Dashboard - -### Tabs - -The topbar holds a `