Commit graph

637 commits

Author SHA1 Message Date
846aa3e680 Linux x86_64 offline release; configurable API and bundled PostgreSQL ports.
- packaging/linux: netx-<ver>-linux-x86_64.tar.gz with bundled Python 3.12,
  PostgreSQL 16 and web/dist (glibc >= 2.17). install.sh (install/update/
  reinstall), netxctl (start/stop/status/logs, set-port, set-bind,
  set-pg-port, reconfigure-db, check-update/update/auto-update, backup,
  uninstall), systemd units, nohup fallback without systemd. Privilege
  drop, detaching and tar go through the bundled Python, so bare images
  without su/runuser/setsid/tar work.
- Updates: same GitHub/Forgejo/manifest sources as Windows, sha256
  verified, pre-update pg_dump, automatic rollback when the new version
  does not come up.
- Non-loopback bind: generated bootstrap admin password and
  NETX_UME_VERIFY_TLS=true, as security_bootstrap requires.
- Build in manylinux2014 + check_bundle.sh (GLIBC <= 2.17, no missing
  libs); release-linux.yml builds on v* tags and smoke-tests offline on
  CentOS 7, Rocky 9, Ubuntu 18.04/24.04, Debian 12, openSUSE Leap 15 and
  openEuler 22.03 before attaching to the release.
- Windows: Setup DB page gets a bundled PG port field and
  /BundledPgPort=; set_pg_port.ps1 + tray "Built-in database port";
  reconfigure keeps the configured port; postgresql.conf is written
  without a BOM (PS 5.1 Set-Content -Encoding utf8 broke postgres).
- Forgejo/GitHub publish scripts include the Linux package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:09:07 +08:00
c141a37263 netx-mcp 0.3.1: fix alarm paging, tool-level arg errors, leaner outputs.
- queryNmsAlarms no longer silently clamps page to 2; add is_cleared.
- Bad integer args return invalid_argument tool errors instead of JSON-RPC crashes.
- Nested {"ok": true, "data": {"ok": false}} results are flagged isError.
- stdio: answer ping, never respond to notifications, version from metadata.
- getNmsNe resolves exact host_name/IP; severity lowercased.
- Outputs use nms_ne_id/source=nms; drop ME{uuid} names, echoed field lists, idle hop_* fields.
- Fabric paths: parallel links count as one hop (edges[].parallel_links).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:46:38 +08:00
aac4521766 Release tooling: slim CI-built runtime, LAN Forgejo uploads.
- The GitHub runner's toolcache keeps python-3.12.x-amd64.exe (~25MB) and
  _test*.pyd next to python.exe; exclude them so CI Setups match local
  ones (0.4.18 CI build was 70MB vs 44MB local).
- publish_forgejo_release.ps1: curl --noproxy for the Forgejo host; a
  desktop HTTP(S)_PROXY returned 502 for the LAN address.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:06:45 +08:00
98c1a1c453 Release 0.4.18: offline-ready installer (VC++ runtime, working service mode), 44MB Setup, update source choice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:49:42 +08:00
a7cc1f502b Fix Windows service mode: it could neither start nor stop.
- Start: WinSW's NetX.out.log/err.log in data\runtime are the same files as
  start_netx.ps1's netx.out.log (case-insensitive) and stay open, so NetX
  could not truncate its log and every start failed. WinSW logs now go to
  data\runtime\service.
- Stop: nothing told the service_run.ps1 supervisor to exit, so it kept
  restarting NetX and WinSW waited forever. stop_netx_app.ps1 writes the
  service.stop flag (-KeepSupervisor for the supervisor's own restarts),
  service_run checks it every second, and runtime_ctl / service_lifecycle
  write it before stopping the service.
- WinSW launched powershell.exe as stop hook never reached the script
  (stuck on inherited std handles); run it via cmd with NUL stdin and output
  to data\runtime\service\stopexec.log. stop_netx_app.ps1 keeps a
  timestamped trace there.

Offline Windows Sandbox: service install -> healthy in 28s, stop in 20s.
Existing service installs need "install service" re-run to pick this up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:46:44 +08:00
c8806c38bd Never wait on the process tree when starting NetX.
Windows PowerShell 5.1 Start-Process -Wait (and `& exe` with captured
output) waits for every descendant / until the stdout pipe closes. The
postgres and NetX processes a start leaves running made runtime_ctl.ps1
never return: tray stuck on "Starting", Start Menu "Start NetX" never
opened the UI. Start-NetxPowerShell -Wait, the UAC relaunch and the Setup
wait in check_update now wait for the process itself (WaitForExit).

Service mode in runtime_ctl: start via sc.exe without blocking on
SERVICE_RUNNING; stop writes the supervisor stop flag, polls up to 120s,
then kills the WinSW tree as a last resort.

Verified in an offline Windows Sandbox (no VC++ redist, no Python).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:46:44 +08:00
ce9a78b5ec Fix MikroTik command output reads without resending commands 2026-10-13 23:17:18 +08:00
a9a1c284a5 Deploy the VC++ runtime app-local for the bundled PostgreSQL.
The EDB binaries link vcruntime140 (and msvcp140 via ICU), which a clean
Windows install lacks, so the built-in DB and the wizard's external-DB
connection test (psql) failed on fresh/offline PCs without the VC++
2015-2022 redistributable. Copy vcruntime140(_1)/msvcp140(_1,_2) into
postgres\pgsql\bin at build time and extract vcruntime140 with psql.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:55:08 +08:00
6ff10834e5 Tray: choose the update source (GitHub default, or git.avelo.top only).
Settings -> Update source writes NETX_UPDATE_SOURCES to ProgramData .env:
empty keeps the default (GitHub first, git.avelo.top mirror as fallback),
"forgejo" pins updates to git.avelo.top.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:31:42 +08:00
19ab1a64a1 Replace pandas with a small openpyxl/csv reader for imports.
pandas + numpy were ~60MB of the shipped venv for three call sites (alarm
Excel import, managed-NE import, import template). netx_api/tabular.py
reads/writes xlsx and csv and parses spreadsheet timestamps.

Checked against the pandas version on the same inputs: timestamp parsing
identical for 24 formats, managed-NE csv/xlsx import, stored rows and both
templates identical. Differences, all fixes:
- alarm codes in mixed text/number columns are "1001", not "1001.0"
- error row numbers are the real sheet rows (blank rows no longer shift them)
- GBK-encoded CSVs (Chinese Excel "Save as CSV") import instead of failing
- "2024年1月2日 03:04:05" style timestamps parse

Also: conftest compares parsed DB URLs (newer SQLAlchemy renders "C:" as
"C%3A").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:15:30 +08:00
e2e6c09825 Ship a runtime-only PostgreSQL and the small WinSW build.
- PostgreSQL: keep postgres/pg_ctl/initdb/psql/pg_dump(all)/pg_restore/
  pg_isready; drop StackBuilder + wx DLLs, dev/test tools, static .lib,
  pgxs and non-Chinese message catalogs (123MB -> 62MB unpacked).
- WinSW: .NET Framework 4.6.1 build (0.6MB, in-box on Win10 1607+ /
  Server 2016+) instead of the self-contained x64 build (18MB).
  install_service.ps1 still accepts an older bundled WinSW-x64.exe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:15:30 +08:00
7a4e2b9477 Drop docs, stdlib tests and Tk/IDLE from the bundled Python runtime.
NetX runs headless; these were ~70MB of the runtime (107MB -> 34MB) and made
CI Setups ~30MB larger than local ones. Setup: 105MB (CI) / 75MB -> 67MB.
ensurepip stays for venv creation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:46:51 +08:00
a82e546918 Make local Windows release builds work without GitHub.
- Prefer Python 3.12 (py -3.12 / Python312) even when another version is
  first on PATH, matching the CI pin.
- Skip npm ci when node_modules already matches package-lock.json: npm ci
  wipes node_modules first and a running Vite dev server leaves it
  half-deleted.
- pip --no-warn-script-location: its PATH check realpath()s every entry
  and aborts on a broken reparse point.
- README: local release / Forgejo / offline steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:38:31 +08:00
1b2b8cef2b Release 0.4.17: modern installer and tray, service-aware start/stop, lifecycle fixes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:11:26 +08:00
ac162dff4e Redo the login page: static milky-way sky and a droplet-glass card.
The space photo is replaced by a seeded canvas sky (nebula band, dust
lanes, stars) painted once. The card refracts the sky at its rim through
an SVG displacement filter (Chromium; plain blur elsewhere), sits further
from the right edge, and drops the glowing flare and button shadow.

Login errors now read as text instead of API codes, the last username is
remembered, and Caps Lock is flagged in the password field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:09:27 +08:00
e21719b66c Modernize the Windows installer, tray and runtime control; fix lifecycle bugs.
Installer: dynamic light/dark Win11 style, new brand wizard images, auto
language, exclusive run mode (tray / Windows service) plus autostart and
auto-update on the Tasks page (pre-selected from what is installed on
upgrades, untouched by silent updates), 5 localized Start Menu entries.

Tray: theme-aware rounded menu with live status, icons and status-dot tray
icon; health polled off the UI thread; Settings submenu toggles autostart
and daily updates; browser opened de-elevated via explorer.

Fixes:
- tray Stop/Start was ignored in service mode (service_run restarted the
  children) - all start/stop now goes through runtime_ctl.ps1
- logon tray task and SYSTEM service task were killed after 72h (default
  ExecutionTimeLimit); autostart was registered for the elevating account
  and opened a browser on every logon
- uninstall left the NetXTray/NetXUpdate tasks behind
- silent auto-update killed the tray without restarting it
- repair_venv.ps1 was never staged into the release
- wildcard NETX_HOST (0.0.0.0) broke health checks
- ICO frames were PNG, which System.Drawing decodes as noise; icons now
  use the current brand mark

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:32:33 +08:00
4c4c7d91d0 Give background children an empty stdin so Vite stops eating shell keystrokes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:18:47 +08:00
96244daba7 Shorten English launcher labels so they fit under the app icons.
"Network Management" -> "Network", "NE Management" -> "NE Mgmt", etc.
Tiles show the full module title on hover and in the aria-label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 16:09:31 +08:00
35d58a3688 Render workbench modules as phone-style app icons.
Drop the card chrome: a 60px rounded tone icon with the name below, in
fixed 96px cells. Hover lifts the icon only; edit mode puts the remove
button on the icon corner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:43:43 +08:00
2307f19779 Let users pick and order their workbench module tiles.
Per-user layout lives in the new app_user.prefs JSON column, read via
/v1/auth/me and written via PUT /v1/auth/me/prefs/workbench. The
workbench gets an in-place edit mode (gear -> drag to reorder, x to
remove, tray to add back, reset/done). Reset stores empty prefs so
registry changes still apply; ids of modules the user can't currently
see are kept on save.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:31:51 +08:00
313706595d Tone down the glass theme: no glows, softer rims, dimmer text.
- Glass: backdrop dimmed (brightness 0.82, saturate 120%), white sheen and
  inner glow removed, specular rim now a faint blue line instead of white.
- Inner borders (tiles, tables, KPI strips, tag cards, controls) use a faint
  blue hairline; top-edge white highlights removed.
- Removed glows: brand mark, primary buttons, tile hover, active tag card,
  task status dots (also no pulse).
- Wallpaper color pools, light streaks and dot grid at ~1/4 of before.
- Text and accent tokens one step dimmer so copy no longer glares on the
  dark background.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:00:25 +08:00
ec19102446 Fix NE page lint errors, topology tree overflow and NE row height.
- NE page: derive the live connect-detail row instead of syncing it in an
  effect; one async path for topology deep links; memoize per-tag stats;
  re-seed the form dialog during render on open; move hop form state into
  lib/hopProxy so the component file only exports components.
- NE page: drop the "click a card to filter" hint; keep row actions on one
  line so rows no longer double in height.
- Topology tree: rows fit the sidebar, long names ellipsize with a tooltip,
  node counts stay visible; default sidebar width 260 -> 280.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:51:37 +08:00
8ecbb13f52 Redesign the shell and console with a liquid-glass look.
- Title bar: floating glass capsule aligned to each page's content edge, new
  NETX mark (links-as-X), task badge, user menu with sign-out, globe locale.
- Console: resource strip on top, module launcher as the main area with
  fixed-size tiles that fill rows as modules are added, task rail sized to
  the left column; dropped health pill, refresh button and filler copy.
- Glass layer (theme/glass.css, loaded last): black-blue wallpaper with a
  faint dot grid, clear panels with specular rims, translucent controls and
  table headers; sidebar pages float their nav and work area on a 16px gutter.
- Removed ~280 lines of duplicated header CSS from primitives/theme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:51:37 +08:00
0ecff329cf Fold NE selection and refresh status into the shared list pager.
Add an optional ListPager meta slot so Managed NE no longer needs a separate selection row above the table.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 00:41:37 +08:00
312f6f2f96 Improve managed NE filters/validation and simplify the workbench UI.
Add column filters and clearer API error mapping for NE management, tighten port validation, and slim the workbench into reusable modules with cleaner styles.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 00:26:58 +08:00
3c9e0efd2b feat: unify network and topology table column filters
Replace top filter bars with shared Excel-style column menus, fix select-all and modal interactions, and use plain dropdown indicators. Apply exact-value filters before pagination and export. Isolate pytest database state and cover filter behavior.
2026-10-12 23:36:00 +08:00
ed820126df Fix the 5 failing netx-topology-mcp tests.
Stale tests (behavior changed intentionally on 2026-08-12):
- Tool count is 16: suggestSinkHubs and classifyTopologyFabricNodes are
  documented public tools; assert them by name.
- compose_views is no longer a public layout action; assert it is
  rejected, and cover the background-job path via orbit_sweep instead.
- Dual-unit petals are nested ellipse bands with a hollow eye, not
  parallel lanes; assert side split, ordering inside the portals and
  zero crossings instead of portal-aligned lane ends.

Real bug (test failed since it was added on 2026-08-09):
press_hot_edges could never reel a long spoke in to its r_use target,
because max_disp (r0*0.55) is smaller than r0 - r_use. Inward pulls along
the spoke cannot fling a leaf across the bbox, so give them a cap of
r0 - r_use. On a 1483-node dev view crossings after the op drop
25501 -> 25346; a 500-node view is unchanged; runtime unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:16:37 +08:00
f301544b99 Optimize topology canvas per the 2026-10-12 plan.
Save path: one atomic POST /views/{id}/commit (edges, ports, styles, node
add/remove, positions) replaces the multi-request save. Edge styles and
manual-edge port edits now go through dirty/undo/save instead of writing
immediately; non-manual edge ports are read-only.

Data safety: UI saves no longer clear MCP node locks or freeze the device
name into the placement label (label_override + omit-means-keep semantics,
also applied to the MCP positions tool). Adding NEs/neighbors with unsaved
edits now saves first instead of silently dropping them. Positions no longer
bypass membership caps, except persisting synthesized child-region icons.

Fixes found in acceptance: nodes added in the same commit kept (40,40)
under autoflush=False; edits on edges deleted in the same save 404'd the
whole save; box-selection drags and arrow-key moves were not marked dirty;
large canvases far from the origin opened blank and locate did nothing
because fitView waits for measurement that onlyRenderVisibleElements never
does (now fitBounds from known geometry).

Also: batch N+1 lookups in graph/positions, deterministic truncation,
outside-peer scan excludes internal edges, split TopologyPage into hooks,
fix flaky UME/LLDP port test, add scripts/topology_clear_frozen_labels.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:11:22 +08:00
60a0ea6021 Release 0.4.16: keep the login earth spinning under reduced motion.
theme.css squashes every animation to 0.01ms x1 when the OS asks for reduced
motion, so the login earth jumped once and snapped back (position stuck at 0%).
The login stylesheet already intends the ambient spin to stay; restore it with a
class selector that outranks the universal rule.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 19:40:05 +08:00
06d2df1b1f Retry interrupted PostgreSQL release downloads 2026-10-12 17:20:12 +08:00
19d4597b94 Fix Python runtime cleanup on upgrade 2026-10-12 17:11:48 +08:00
5e80932c4a Fix Windows release web build
Some checks failed
Release Windows / build (push) Has been cancelled
2026-10-12 15:56:06 +08:00
a5c9a8f58d Prepare NetX 0.4.14 Windows release 2026-10-12 15:54:53 +08:00
af8d5a8d37 Track web/src/features/ume: anchor the ume/ ignore rule to the repo root.
Some checks failed
Release Windows / build (push) Has been cancelled
The unanchored 'ume/' rule also matched web/src/features/ume/, so UmePage was
never committed and clean checkouts failed to build (App.tsx imports it).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 14:59:26 +08:00
315539e0fd Optimize cutover compare/monitor per the 2026-10-12 plan.
Correctness (A): normalize port-map names with the template rules (snapshot v2,
v1 replays unchanged); protect mappings/templates that are referenced; stop
dropping edited mapping text; accept pulled-but-not-shutdown ports as migrated;
validate baseline ownership on project create; one canonical key form; fix
built-in template tolerances and upgrade old packaged values in place.

Cross-vendor identity (B): single identity pipeline for every path, per-side and
per-vendor interface rules, value maps, filters after normalization, mapping
pre-flight for compare and cutover projects, SQL eligibility fixes.

Data quality (V): no_data / suspect_parse / not_collected sheet states, command
slice coverage, directional compare modes, value-sorted duplicate pairing,
before-side raw names in results and CSV.

Robustness (H): bounded auto-run history, background evaluate/finish with
polling, manual route tables out of the acceptance gate, baseline row cache,
scoped duplicate-key failures, merged HF tasks with a per-NE session cap,
same-device cutover, explicit scope_by_port_map, read-only GETs, resolvable red
tickets.

Frontend: pre-flight report, mapping table view, template editor support for the
new rules, data-state banners. Docs: canonical field contract.

Not included: Huawei status parsers (no real samples), SQL-path route compare.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 11:51:55 +08:00
fff7d63b9b Ignore Claude Code local settings.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 07:37:51 +08:00
e3a15c3d7b Add page-size selector and jump-to-page to the audit log table.
Use the shared ListPager (10/20/50/100/200 per page, remembered in
localStorage, default 20 instead of a fixed 10), keep the previous rows while the
next page loads and clamp the page when the total shrinks.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 07:34:30 +08:00
45de8144a3 Speed up WebCRT and record audited commands from the device echo.
Performance: event-driven stdout pump (no polling thread per socket, no 200ms
coalescing stall), keystrokes written immediately, blocking SSH reads, bounded
deque queue with batch drain, incremental UTF-8 decode, buffered session log,
non-blocking session teardown, shorter login/settle waits, xterm WebGL renderer
and idle-time direct writes. Zero-latency fake device: echo p50 11ms -> 2.3ms,
command RTT 219ms -> 20ms, bulk output 2.1 -> 8.3 MB/s.

Audit: track the device's own input row server-side (webcrt_cmd_audit) and
resolve each Enter from the echoed line feed, so Tab, backspace, cursor-key
edits, history recall, paste, Ctrl-C and pagers record what actually ran.
Password lines are redacted; pending Enters are flushed on close.

Hop: stop closing the hop session when the target prints the same prompt as the
hop (system-view); recognise the Huawei "closed by the remote host" message.
Generic NEs that show a network prompt now get the network key map.

Adds bench_webcrt.py, fake_ssh_device.py and e2e_webcrt_input_scenarios.py.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 07:34:30 +08:00
0d894efe5e Refactor web UI: feature-first structure, tokenized styles, modern blue theme.
Structure
- pages/ -> features/<domain>/{Page, components, hooks, lib}; 95 files moved,
  333 imports rewritten, verified with tsc.
- services/api.ts -> services/api/<domain>.ts (250 exports preserved),
  types.ts -> types/<domain>.ts, i18n zh/en -> locales/<lang>/<namespace>.ts
  (2696 messages deep-equal before/after).
- ESLint rule: shared layers must not import features/.

Styles
- index.css (16k lines) split losslessly into styles/{base,layout,components,
  pages,legacy,theme}; compiled CSS was byte-identical before tokenizing.
- ~930 hard-coded colors replaced by --nx-* tokens (theme/tokens.css); WebCRT
  off-palette colors unified; fixed dark-on-dark text introduced by mapping.
- theme/theme.css: modern blue design language (rounded shapes, gradients,
  unified buttons/fields/tables/modals), form-grid alignment fix, flat nav list
  without tree indent, soft selected state instead of left accent bar.

Docs: WEB.md documents code structure and style rules.
Not touched: the large Biz*/Webcrt/Topology page components (to be split later).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 03:17:51 +08:00
3b45d6abe3 Improve WebCRT connect UX and terminal input handling.
Open shells asynchronously with clearer prompt settling, fix Telnet CRLF expansion, and add right-click paste with safer focus behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-11 22:55:31 +08:00
1463652dbb Tighten NetX help copy and structure HelpHint typography.
Remove permanent list-page hint banners, keep concepts in short HelpHint popovers with scannable sections and lists.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-11 16:44:10 +08:00
046029aa16 Unify NetX UI to compact ops chrome and add API key purge.
Align network/list shells and audit header with industrial panels; allow permanently deleting revoked API keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-11 16:20:31 +08:00
4d60601050 feat(cutover): add live fullscreen monitoring wall 2026-10-11 09:08:03 +08:00
b9d5e27cc4 feat(cutover-ui): show paired timing and manual route configuration 2026-10-11 08:48:20 +08:00
d3618deff6 feat(cutover): pair metric collection rounds and isolate manual routes 2026-10-11 08:46:46 +08:00
32d7d969f6 feat: refine cutover operations board and monitoring performance
Protect previous wave coverage, normalize batch identities, cache shared metric evidence, and batch diff inserts. Add live continuity KPIs, server paging and filters, scoped business selection, and preserve legacy monitor rule metadata.

Validation: 198 backend tests passed with 1 opt-in benchmark skipped; 14 frontend unit tests and 24 browser checks passed; TypeScript and production build passed.
2026-10-11 07:55:04 +08:00
fe4c1db763 fix: enforce business continuity and live cutover monitoring 2026-10-11 07:33:17 +08:00
355bcfc4c0 feat(biz-compare): preserve templates and refine industrial editor 2026-10-11 06:06:20 +08:00
90cf1907b4 fix(biz-compare): validate templates and protect comparison inputs 2026-10-11 05:56:09 +08:00
8c15975d3e Refine business monitoring UI and protect asynchronous navigation 2026-10-11 00:30:30 +08:00