# Phase 4: Minimal Operator/Admin UI

**Date**: 2026-03-16
**Status**: Draft

---

## Scope

**Goal**: Operators can manage sites, monitor health, and control instance lifecycle from the browser.

**Component**: Central UI (admin + operator workflows)

**Testable Outcome**: Admin manages sites, data connections, areas, LDAP mappings, API keys. Operator sees health dashboard with live SignalR push, manages instance lifecycle, views deployment status.

**HighLevelReqs Coverage**: 8 (partial — admin and operator workflows), 7.2 (API key management), 3.8.1 (partial — UI for lifecycle), 3.10 (partial — UI for area management)

---

## Prerequisites

| Phase | What Must Be Complete | Why |
|-------|----------------------|-----|
| Phase 0 | Solution skeleton, Commons types, Host | Project structure, shared types, Host boot |
| Phase 1 | Configuration Database, Security & Auth, Central UI shell | DB schema, repos, auth, Blazor shell, route guards, JWT |
| Phase 2 | Template Engine (template/instance/area/site/data-connection model) | Data model for sites, areas, data connections, instances |
| Phase 3A | Cluster Infrastructure, Site Runtime (skeleton) | Cluster and Instance Actor basics for lifecycle commands |
| Phase 3B | Health Monitoring (site collection + central aggregation), Communication Layer | Health data flowing to central, communication for queries |
| Phase 3C | Deployment Manager (full), Store-and-Forward | Deployment pipeline, lifecycle commands, deployment status |

---

## Requirements Checklist

### Section 7.2 — API Key Management

- [ ] `[7.2-1]` API keys are stored in the configuration database.
- [ ] `[7.2-2]` Each API key has a name/label (for identification).
- [ ] `[7.2-3]` Each API key has the key value.
- [ ] `[7.2-4]` Each API key has an enabled/disabled flag.
- [ ] `[7.2-5]` API keys are managed by users with the Admin role.

### Section 8 — Central UI (Phase 4 portion: admin and operator workflows)

#### Site & Data Connection Management (Admin Role)

- [ ] `[8-site-1]` Create, edit, and delete site definitions.
- [ ] `[8-site-2]` Define data connections and assign them to sites (name, protocol type, connection details).

#### Area Management (Admin Role)

- [ ] `[8-area-1]` Define hierarchical area structures per site.
- [ ] `[8-area-2]` Parent-child area relationships.
- [ ] `[8-area-3]` Assign areas when managing instances. **Note**: Instance creation with area assignment is Phase 5 (design-time workflows). Phase 4 surfaces area as a display/filter field on the instance list and as context for lifecycle actions.

#### LDAP Group Mapping (Admin Role)

- [ ] `[8-ldap-1]` Map LDAP groups to system roles (Admin, Design, Deployment).
- [ ] `[8-ldap-2]` Configure site-scoping for Deployment role groups.

#### Inbound API Management — API Key CRUD (Admin Role, Phase 4 portion)

- [ ] `[8-apikey-1]` Create API keys (name/label, key value, enabled flag).
- [ ] `[8-apikey-2]` Enable/disable API keys.
- [ ] `[8-apikey-3]` Delete API keys.
- [ ] `[8-apikey-4]` All API key changes are audit logged.

#### Instance Management (Deployment Role, Phase 4 portion — lifecycle actions only)

- [ ] `[8-inst-1]` Filter/search instances by site, area, template, or status.
- [ ] `[8-inst-2]` Disable instances — stops data collection, script triggers, and alarm evaluation while retaining deployed configuration.
- [ ] `[8-inst-3]` Enable instances — re-activates a disabled instance.
- [ ] `[8-inst-4]` Delete instances — removes running configuration from site. Blocked if site is unreachable. Store-and-forward messages are not cleared.
- [ ] `[8-inst-5]` Instance list with status indicators (enabled, disabled, not deployed).

#### Deployment Status (All roles with access)

- [ ] `[8-deploy-1]` Track deployment status: pending, in-progress, success, failed.
- [ ] `[8-deploy-2]` Deployment status transitions push to the UI immediately via SignalR (no polling).

#### Health Monitoring Dashboard (All Roles)

- [ ] `[8-health-1]` Overview of all sites with online/offline status.
- [ ] `[8-health-2]` Per-site detail: active/standby node status.
- [ ] `[8-health-3]` Per-site detail: data connection health (connected/disconnected per connection).
- [ ] `[8-health-4]` Per-site detail: script error rates.
- [ ] `[8-health-5]` Per-site detail: alarm evaluation error rates.
- [ ] `[8-health-6]` Per-site detail: store-and-forward buffer depths (by category: external, notification, DB write).
- [ ] `[8-health-7]` Health dashboard updates automatically via SignalR when new health reports arrive — no manual refresh or polling.

### Section 3.8.1 — Instance Lifecycle (Phase 4 portion: UI surfacing)

- [ ] `[3.8.1-ui-1]` Instance lifecycle commands (disable, enable, delete) are surfaced in the Central UI.
- [ ] `[3.8.1-ui-2]` Delete is blocked if the site is unreachable — UI must communicate this clearly.
- [ ] `[3.8.1-ui-3]` Store-and-forward messages are not cleared on deletion — UI does not imply otherwise.

### Section 3.10 — Areas (Phase 4 portion: UI management)

- [ ] `[3.10-ui-1]` Areas are predefined hierarchical groupings associated with a site, managed in the UI.
- [ ] `[3.10-ui-2]` Areas support parent-child relationships in the UI (tree/hierarchy visualization).
- [ ] `[3.10-ui-3]` Areas are used for filtering and finding instances in the Central UI.
- [ ] `[3.10-ui-4]` Area definitions are managed by users with the Admin role.

### Section 11.1–11.2 — Health Monitoring (Phase 4 portion: dashboard display)

- [ ] `[11-ui-1]` Site cluster online/offline status displayed.
- [ ] `[11-ui-2]` Active vs. standby node status displayed.
- [ ] `[11-ui-3]` Data connection health (connected/disconnected) per connection displayed.
- [ ] `[11-ui-4]` Script error rates displayed.
- [ ] `[11-ui-5]` Alarm evaluation error rates displayed.
- [ ] `[11-ui-6]` Store-and-forward buffer depth displayed (broken down by category).
- [ ] `[11-ui-7]` Health status is visible in the central UI (display-only, no automated alerting).

### Section 13.1 — Timestamps (Phase 4 portion: display)

- [ ] `[13.1-ui-1]` Local time conversion for display is a Central UI concern — timestamps shown in user-local time where appropriate.

---

## Design Constraints Checklist

### From CLAUDE.md Key Design Decisions

- [ ] `[KDD-ui-1]` Central UI: Blazor Server (ASP.NET Core + SignalR). Bootstrap CSS, no heavy frameworks. Custom components. Clean corporate design for internal use.
- [ ] `[KDD-ui-2a]` Real-time push for health dashboard via SignalR (server push, no polling).
- [ ] `[KDD-ui-2b]` Real-time push for deployment status via SignalR.
- [ ] `[KDD-ui-3a]` Health reports displayed as "X errors in the last 30 seconds" (raw counts per interval).
- [ ] `[KDD-sec-4a]` Load balancer in front of central UI — UI must work behind load balancer (no sticky sessions, JWT-based).
- [ ] `[KDD-deploy-10a]` Deployment status view shows current status only (no deployment history table — audit log provides history).

### From docs/requirements/Component-CentralUI.md

- [ ] `[CD-CentralUI-1]` No live machine data visualization — UI is focused on system management (except debug views, which are Phase 6).
- [ ] `[CD-CentralUI-2]` Role-based access control enforced in UI: Admin, Design, Deployment with site scoping.
- [ ] `[CD-CentralUI-3]` Failover behavior: SignalR circuit interrupted on failover, auto-reconnect. JWT survives, no re-login.
- [ ] `[CD-CentralUI-4]` Central UI accesses configuration data via `ICentralUiRepository` (read-oriented queries).
- [ ] `[CD-CentralUI-5]` Health dashboard: no historical data — current/latest status only (in-memory at central).

### From docs/requirements/Component-HealthMonitoring.md

- [ ] `[CD-Health-1]` Health metrics held in memory at central — dashboard shows current/latest status only.
- [ ] `[CD-Health-2]` Online recovery: site automatically marked online when health report received after offline period.
- [ ] `[CD-Health-3]` Tag resolution counts displayed (per connection: total subscribed vs. successfully resolved).
- [ ] `[CD-Health-4]` Dead letter count displayed as a health metric.
- [ ] `[CD-Health-5]` No alerting — health monitoring is display-only.
- [ ] `[CD-Health-6]` Error rate metrics: script errors include unhandled exceptions, timeouts, recursion limit violations. Alarm evaluation errors include all failures during condition evaluation.

### From docs/requirements/Component-Security.md

- [ ] `[CD-Sec-1]` Admin role permissions include: manage sites, data connections, areas, LDAP mappings, API keys, system config, view audit logs. **Phase 4 covers**: sites, data connections, areas, LDAP mappings, API keys. **Phase 6 covers**: audit log viewer. System config is not a separate page — it is covered by the individual admin workflows.
- [ ] `[CD-Sec-2]` Deployment role permissions include: manage instances (lifecycle), deploy, view deployment status, debug view, parked messages, event logs. Site-scoped Deployment only sees their permitted sites. **Phase 4 covers**: instance lifecycle, instance list, deployment status. **Phase 5 covers**: instance create/overrides/binding. **Phase 6 covers**: deploy action, debug view, parked messages, event logs.
- [ ] `[CD-Sec-3]` Every UI action checks authenticated user's roles before proceeding.
- [ ] `[CD-Sec-4]` Site-scoped Deployment checks verify target site is within user's permitted sites.

### From docs/requirements/Component-InboundAPI.md

- [ ] `[CD-Inbound-1]` API key properties: name/label, key value, enabled/disabled flag.
- [ ] `[CD-Inbound-2]` All key changes (create, enable/disable, delete) are audit logged.

### From docs/requirements/Component-DeploymentManager.md

- [ ] `[CD-Deploy-1]` Deployment status: pending, in-progress, success, failed — only current status stored.
- [ ] `[CD-Deploy-2]` Per-instance operation lock — UI must handle "operation in progress" error gracefully.
- [ ] `[CD-Deploy-3]` Allowed state transitions matrix enforced (e.g., cannot disable an already-disabled instance).
- [ ] `[CD-Deploy-4]` Delete fails if site is unreachable — central does not mark as deleted until site confirms.

---

## Work Packages

### WP-1: Site Management CRUD (Admin)

**Description**: Build the site management pages — create, edit, and delete site definitions.

**Acceptance Criteria**:
- Admin can create a site with name, identifier, and description.
- Admin can edit site details.
- Admin can delete a site (with confirmation dialog; blocked if instances exist at the site).
- Non-Admin users cannot access site management.
- Site changes are audit logged.
- Form validation: required fields, unique identifier.
- Success/error notifications displayed after operations.

**Estimated Complexity**: M

**Requirements Traced**: `[8-site-1]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[CD-Sec-3]`, `[KDD-ui-1]`

---

### WP-2: Data Connection Management (Admin)

**Description**: Build data connection definition pages — create, edit, delete data connections and assign them to sites.

**Acceptance Criteria**:
- Admin can create a data connection with name, protocol type, and connection details.
- Admin can assign/unassign data connections to/from sites.
- Admin can edit data connection details.
- Admin can delete a data connection (blocked if bound to any instance attribute).
- Protocol type selection (OPC UA, LmxProxy).
- Connection details form varies by protocol type.
- Non-Admin users cannot access data connection management.
- Data connection changes are audit logged.

**Estimated Complexity**: M

**Requirements Traced**: `[8-site-2]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[CD-Sec-3]`, `[KDD-ui-1]`

---

### WP-3: Area Management (Admin)

**Description**: Build hierarchical area management pages — create, edit, delete area structures per site.

**Acceptance Criteria**:
- Admin can create areas within a site.
- Admin can create child areas under parent areas (hierarchical tree).
- Admin can edit area names.
- Admin can delete areas (blocked if instances are assigned to the area or its descendants).
- Tree/hierarchy visualization of area structure.
- Area management is scoped to a selected site.
- Non-Admin users cannot access area management.
- Area changes are audit logged.

**Estimated Complexity**: M

**Requirements Traced**: `[8-area-1]`, `[8-area-2]`, `[3.10-ui-1]`, `[3.10-ui-2]`, `[3.10-ui-4]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[KDD-ui-1]`

---

### WP-4: LDAP Group Mapping Management (Admin)

**Description**: Build the LDAP group-to-role mapping management page.

**Acceptance Criteria**:
- Admin can create a mapping: LDAP group name to role (Admin, Design, Deployment).
- Admin can configure site-scoping for Deployment role mappings (all sites or specific sites).
- Admin can edit existing mappings.
- Admin can delete mappings (with confirmation).
- Table view of all current mappings with role and scope columns.
- Non-Admin users cannot access LDAP mapping management.
- Mapping changes are audit logged.

**Estimated Complexity**: S

**Requirements Traced**: `[8-ldap-1]`, `[8-ldap-2]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[CD-Sec-3]`, `[KDD-ui-1]`

---

### WP-5: API Key Management (Admin)

**Description**: Build the API key management page for the Inbound API.

**Acceptance Criteria**:
- Admin can create an API key with name/label and auto-generated or user-provided key value.
- API keys are persisted to the configuration database (verified by integration test: create key, query DB, confirm stored).
- Admin can enable/disable an API key via toggle.
- Admin can delete an API key (with confirmation).
- Table view of all keys showing name, enabled/disabled status, creation date.
- Key value displayed only once on creation (or with explicit reveal action) for security.
- Non-Admin users cannot access API key management.
- All key changes (create, enable/disable, delete) are audit logged.

**Estimated Complexity**: S

**Requirements Traced**: `[7.2-1]`, `[7.2-2]`, `[7.2-3]`, `[7.2-4]`, `[7.2-5]`, `[8-apikey-1]`, `[8-apikey-2]`, `[8-apikey-3]`, `[8-apikey-4]`, `[CD-Inbound-1]`, `[CD-Inbound-2]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[KDD-ui-1]`

---

### WP-6: Instance List with Filtering (Deployment Role)

**Description**: Build the instance list page with filtering capabilities and status display.

**Acceptance Criteria**:
- Deployment users can view all instances (or site-scoped subset).
- Filter by site, area, template, and status (enabled, disabled, not deployed).
- Instance list shows: instance name, template name, site name, area, status.
- Area filter uses hierarchical selection (selecting a parent area includes children).
- Site-scoped Deployment users only see instances at their permitted sites.
- Non-Deployment users cannot access instance management.
- Pagination for large instance lists.

**Estimated Complexity**: M

**Requirements Traced**: `[8-inst-1]`, `[8-inst-5]`, `[8-area-3]`, `[3.10-ui-3]`, `[CD-CentralUI-2]`, `[CD-CentralUI-4]`, `[CD-Sec-2]`, `[CD-Sec-4]`, `[KDD-ui-1]`

---

### WP-7: Instance Lifecycle Actions (Deployment Role)

**Description**: Build instance lifecycle action buttons and flows — disable, enable, delete.

**Acceptance Criteria**:
- Disable button: sends disable command via Deployment Manager, updates instance status to disabled. Confirmation dialog explains that disable stops data subscriptions, script triggers, and alarm evaluation while retaining the deployed configuration.
- Enable button: sends enable command via Deployment Manager, updates instance status to enabled. Confirmation dialog.
- Delete button: sends delete command via Deployment Manager. Confirmation dialog warns about permanent removal and explicitly states that store-and-forward messages will continue to be delivered (not cleared).
- Delete blocked if site is unreachable — error message explains the site must be reachable. Instance remains in its current state until site confirms deletion.
- UI clearly communicates that store-and-forward messages are not cleared on deletion (in confirmation dialog and any post-delete status messages).
- Buttons are contextually enabled/disabled based on allowed state transitions (e.g., cannot disable an already-disabled instance, cannot enable a not-deployed instance).
- "Operation in progress" state shown when another mutating operation is in-flight for the instance.
- Site-scoped Deployment users can only act on instances at permitted sites.
- All lifecycle actions are audit logged.
- Long-running action indicator while waiting for site confirmation.

**Estimated Complexity**: M

**Requirements Traced**: `[8-inst-2]`, `[8-inst-3]`, `[8-inst-4]`, `[3.8.1-ui-1]`, `[3.8.1-ui-2]`, `[3.8.1-ui-3]`, `[CD-CentralUI-2]`, `[CD-Deploy-2]`, `[CD-Deploy-3]`, `[CD-Deploy-4]`, `[CD-Sec-2]`, `[CD-Sec-4]`, `[KDD-ui-1]`

---

### WP-8: Deployment Status View (Deployment Role)

**Description**: Build the deployment status display with real-time updates via SignalR.

**Acceptance Criteria**:
- Deployment status visible on instance list and instance detail: pending, in-progress, success, failed.
- Status transitions push to the UI in real-time via SignalR — no polling.
- Failed deployments show failure reason.
- Current status only (no deployment history — audit log provides history).
- Status indicators use clear visual treatment (color-coded badges or icons).
- Long-running deployment shows in-progress indicator.

**Estimated Complexity**: M

**Requirements Traced**: `[8-deploy-1]`, `[8-deploy-2]`, `[KDD-ui-2b]`, `[KDD-deploy-10a]`, `[CD-Deploy-1]`, `[KDD-ui-1]`

---

### WP-9: Health Monitoring Dashboard (All Roles)

**Description**: Build the health monitoring dashboard with live SignalR push showing all site health metrics.

**Acceptance Criteria**:
- Overview page: all sites listed with online/offline status indicators.
- Clicking a site navigates to per-site detail view.
- Per-site detail shows:
  - Active/standby node status.
  - Data connection health: connected/disconnected per connection.
  - Tag resolution counts per connection (subscribed vs. resolved).
  - Script error rates ("X errors in the last 30 seconds").
  - Alarm evaluation error rates ("X errors in the last 30 seconds").
  - Store-and-forward buffer depths by category (external, notification, DB write).
  - Dead letter count.
- Dashboard updates automatically via SignalR when health reports arrive — no manual refresh.
- Site automatically transitions between online/offline based on health report presence (60s threshold).
- Online recovery shown automatically when health report received after offline period.
- Health data is current/latest only — no historical data displayed.
- No alerting functionality — display-only.
- All roles can access the health dashboard.
- No live machine data visualization anywhere in Phase 4 pages — health dashboard shows management/operational metrics only.
- Error rate descriptions include what constitutes an error (tooltip or help text).

**Estimated Complexity**: L

**Requirements Traced**: `[8-health-1]`, `[8-health-2]`, `[8-health-3]`, `[8-health-4]`, `[8-health-5]`, `[8-health-6]`, `[8-health-7]`, `[11-ui-1]`, `[11-ui-2]`, `[11-ui-3]`, `[11-ui-4]`, `[11-ui-5]`, `[11-ui-6]`, `[11-ui-7]`, `[KDD-ui-2a]`, `[KDD-ui-3a]`, `[CD-Health-1]`, `[CD-Health-2]`, `[CD-Health-3]`, `[CD-Health-4]`, `[CD-Health-5]`, `[CD-Health-6]`, `[CD-CentralUI-1]`, `[KDD-ui-1]`

---

### WP-10: Authorization-Aware Navigation

**Description**: Extend the Phase 1 Blazor shell with navigation links for all Phase 4 pages, gated by role.

**Acceptance Criteria**:
- Navigation sidebar/menu shows links based on the authenticated user's roles.
- Admin users see: Site Management, Data Connections, Areas, LDAP Mappings, API Keys.
- Deployment users see: Instance Management, Deployment Status.
- All roles see: Health Dashboard.
- Site-scoped Deployment users see navigation but content is filtered to permitted sites.
- No navigation links shown for pages the user cannot access.
- Attempting to navigate directly to an unauthorized page shows an access denied message.

**Estimated Complexity**: S

**Requirements Traced**: `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[CD-Sec-2]`, `[CD-Sec-3]`, `[KDD-ui-1]`

---

### WP-11: Error/Success Notifications and Long-Running Action Indicators

**Description**: Build shared UX components for toast notifications and long-running action indicators.

**Acceptance Criteria**:
- Toast notification component for success, error, warning, and info messages.
- Notifications auto-dismiss after a configurable duration (success) or persist until dismissed (errors).
- Long-running action indicator (spinner/progress bar) for operations that communicate with sites.
- Loading states on buttons/forms while async operations are in-flight.
- Consistent visual design across all Phase 4 pages using Bootstrap CSS only — no third-party component frameworks (e.g., no Radzen, MudBlazor, Syncfusion). All interactive components are custom Blazor components.
- Clean corporate design suitable for internal industrial use.
- Handles SignalR circuit reconnection gracefully (shows reconnecting state, auto-recovers).
- UI works correctly behind a load balancer — no sticky session dependencies (JWT-based auth from Phase 1 provides this; this WP verifies the UX survives failover without re-login). **Note**: Shared Data Protection keys and JWT infrastructure are Phase 1 concerns; this WP covers the UI-side reconnection behavior only.

**Estimated Complexity**: S

**Requirements Traced**: `[KDD-ui-1]`, `[CD-CentralUI-3]`, `[KDD-sec-4a]`

---

### WP-12: Timestamp Display Formatting

**Description**: Implement UTC-to-local-time conversion for all timestamps displayed in the UI.

**Acceptance Criteria**:
- All timestamps from the backend (UTC) are converted to the user's browser local time for display.
- Consistent date/time format across all pages.
- Hover/tooltip shows UTC value for any displayed timestamp.
- Health report timestamps, deployment timestamps, and audit timestamps all use this formatting.

**Estimated Complexity**: S

**Requirements Traced**: `[13.1-ui-1]`, `[KDD-ui-1]`

---

### WP-13: ICentralUiRepository Extensions for Phase 4

**Description**: Extend the `ICentralUiRepository` interface (Commons) and its implementation (Configuration Database) to support the read-oriented queries needed by Phase 4 UI pages.

**Acceptance Criteria**:
- Query methods for: site list, site detail, data connections by site, areas by site (hierarchical), LDAP group mappings, API keys, instance list with filtering (site, area, template, status).
- Pagination support on instance list.
- Area queries return hierarchical structure.
- Repository methods return Commons POCO entities.
- Write operations for Admin CRUD (sites, data connections, areas, LDAP mappings, API keys) via appropriate repositories.
- All write operations integrate with IAuditService for audit logging.

**Estimated Complexity**: M

**Requirements Traced**: `[CD-CentralUI-4]`, `[8-apikey-4]`, `[KDD-code-1]`, `[KDD-code-2]`

---

## Test Strategy

### Unit Tests

- **Navigation authorization**: Verify role-based navigation link visibility for each role (Admin, Design, Deployment, multi-role, site-scoped).
- **State transition matrix**: Verify button enable/disable logic for instance lifecycle based on current state (enabled/disabled/not-deployed).
- **Timestamp formatting**: Verify UTC-to-local conversion correctness.
- **Filter logic**: Verify instance filtering by site, area (including descendant areas), template, status.
- **Repository queries**: Unit test ICentralUiRepository extension methods against in-memory EF Core provider.

### Integration Tests

- **Site CRUD flow**: Create site, edit, delete. Verify audit log entries.
- **Data connection CRUD flow**: Create, assign to site, edit, delete. Verify audit log entries.
- **Area CRUD flow**: Create root area, create child, delete child, delete root. Verify hierarchical integrity. Verify audit log entries.
- **LDAP mapping CRUD flow**: Create mapping, edit, delete. Verify audit log entries.
- **API key CRUD flow**: Create key, verify stored in config DB. Enable/disable. Delete. Verify audit log entries for each operation.
- **Instance lifecycle flow**: Disable an enabled instance, verify status. Enable a disabled instance, verify status. Attempt to delete with site unreachable, verify failure.
- **Authorization enforcement**: Verify Admin-only pages reject Deployment/Design users. Verify site-scoped Deployment user cannot act on instances outside their permitted sites.
- **Deployment status push**: Trigger a deployment, verify SignalR pushes status transitions to the UI.
- **Health dashboard push**: Inject a health report, verify dashboard updates via SignalR without page refresh.

### Negative Tests

- **Non-Admin cannot access Admin pages** (site management, data connections, areas, LDAP mappings, API keys).
- **Site-scoped Deployment user cannot see or act on instances outside permitted sites**.
- **Cannot disable an already-disabled instance** (button disabled; API returns appropriate error).
- **Cannot enable a not-deployed instance** (button disabled).
- **Cannot delete an instance if site is unreachable** (operation fails with clear error message).
- **Cannot delete a site with assigned instances** (operation blocked).
- **Cannot delete a data connection bound to instance attributes** (operation blocked).
- **Cannot delete an area with assigned instances** (operation blocked).

### Manual/Exploratory Tests

- SignalR reconnection after central failover — health dashboard and deployment status recover.
- Visual review of Bootstrap-based layout, responsive behavior, accessibility.
- Long-running operation indicators appear and dismiss correctly.

---

## Verification Gate

The phase is complete when all of the following pass:

1. All Admin CRUD workflows function end-to-end: sites, data connections, areas, LDAP mappings, API keys.
2. Instance list with filtering displays correctly, respecting site-scoped permissions.
3. Instance lifecycle actions (disable, enable, delete) work end-to-end including site communication.
4. Delete correctly fails when site is unreachable.
5. Health monitoring dashboard displays all metrics with live SignalR push.
6. Deployment status view shows real-time status transitions via SignalR.
7. All role-based access control is enforced — unauthorized access is denied.
8. All CRUD operations produce audit log entries.
9. All timestamps display in user-local time.
10. All integration tests pass.
11. All negative tests pass (unauthorized access, invalid state transitions, unreachable site).

---

## Open Questions

| # | Question | Context | Impact | Status |
|---|----------|---------|--------|--------|
| Q-P4-1 | Should the API key value be auto-generated (GUID/random) or allow user-provided values? | docs/requirements/Component-InboundAPI.md says "key value" but does not specify generation. | Phase 4, WP-5. | Open — assume auto-generated with optional copy-to-clipboard; user can regenerate. |
| Q-P4-2 | Should the health dashboard support configurable refresh intervals or always use the 30s report interval? | docs/requirements/Component-HealthMonitoring.md specifies 30s default interval. | Phase 4, WP-9. | Open — assume display updates on every report arrival (no UI-side polling); interval is server-side config. |
| Q-P4-3 | Should area deletion cascade to child areas or require bottom-up deletion? | docs/requirements/HighLevelReqs 3.10 says "parent-child relationships" but does not specify cascade behavior. | Phase 4, WP-3. | Open — assume cascade delete of child areas (if no instances assigned to any area in the subtree). |

---

## Split-Section Completeness

### Section 8 — Central UI (split across Phases 4, 5, 6)

**Phase 4 covers**:
- Site & Data Connection Management (Admin): `[8-site-1]`, `[8-site-2]`
- Area Management (Admin): `[8-area-1]`, `[8-area-2]`, `[8-area-3]`
- LDAP Group Mapping (Admin): `[8-ldap-1]`, `[8-ldap-2]`
- Inbound API Management — API key CRUD (Admin): `[8-apikey-1]` through `[8-apikey-4]`
- Instance Management — lifecycle actions (Deployment): `[8-inst-1]` through `[8-inst-5]`
- Deployment Status Monitoring: `[8-deploy-1]`, `[8-deploy-2]`
- Health Monitoring Dashboard: `[8-health-1]` through `[8-health-7]`

**Phase 5 covers** (not this plan):
- Template Authoring (Design)
- Shared Script Management (Design)
- External System Management (Design) — definition CRUD only
- Database Connection Management (Design) — definition CRUD only
- Notification List Management (Design) — definition CRUD only
- Inbound API Management — method definition CRUD (Design)
- Instance Management — create, overrides, connection binding, area assignment (Deployment)

**Phase 6 covers** (not this plan):
- Deployment workflow (diffs, validation gating, deploy action)
- System-Wide Artifact Deployment
- Debug View
- Parked Message Management
- Site Event Log Viewer
- Audit Log Viewer

**Union check**: All Section 8 workflows are assigned. No gaps identified.

### Section 3.8.1 — Instance Lifecycle (split across Phases 3C, 4)

**Phase 4 covers**: UI surfacing of lifecycle commands (`[3.8.1-ui-1]` through `[3.8.1-ui-3]`).

**Phase 3C covers**: Backend implementation — Deployment Manager sends disable/enable/delete commands to sites, site-side execution, state management.

**Union check**: Phase 3C handles backend lifecycle mechanics. Phase 4 handles UI. Full coverage.

### Section 3.10 — Areas (split across Phases 2, 4)

**Phase 4 covers**: UI management of areas (`[3.10-ui-1]` through `[3.10-ui-4]`).

**Phase 2 covers**: Area data model, storage, area assignment on instances.

**Union check**: Phase 2 handles model/storage. Phase 4 handles UI management. Full coverage.

### Sections 11.1–11.2 — Health Monitoring (split across Phases 3B, 4)

**Phase 4 covers**: Dashboard display of all health metrics (`[11-ui-1]` through `[11-ui-7]`).

**Phase 3B covers**: Site-side metric collection, periodic reporting, central-side aggregation, offline detection.

**Union check**: Phase 3B handles data collection/aggregation. Phase 4 handles UI display. Full coverage.

---

## Orphan Check Result

### Forward Check (Requirements → Work Packages)

Every item in the Requirements Checklist and Design Constraints Checklist has been mapped to at least one work package:

| Requirement/Constraint | Work Package(s) |
|----------------------|-----------------|
| `[7.2-1]` through `[7.2-5]` | WP-5 |
| `[8-site-1]`, `[8-site-2]` | WP-1, WP-2 |
| `[8-area-1]`, `[8-area-2]`, `[8-area-3]` | WP-3, WP-6 |
| `[8-ldap-1]`, `[8-ldap-2]` | WP-4 |
| `[8-apikey-1]` through `[8-apikey-4]` | WP-5 |
| `[8-inst-1]` through `[8-inst-5]` | WP-6, WP-7 |
| `[8-deploy-1]`, `[8-deploy-2]` | WP-8 |
| `[8-health-1]` through `[8-health-7]` | WP-9 |
| `[3.8.1-ui-1]` through `[3.8.1-ui-3]` | WP-7 |
| `[3.10-ui-1]` through `[3.10-ui-4]` | WP-3, WP-6 |
| `[11-ui-1]` through `[11-ui-7]` | WP-9 |
| `[13.1-ui-1]` | WP-12 |
| `[KDD-ui-1]` | WP-1 through WP-12 (all) |
| `[KDD-ui-2a]`, `[KDD-ui-2b]` | WP-8, WP-9 |
| `[KDD-ui-3a]` | WP-9 |
| `[KDD-sec-4a]` | WP-11 |
| `[KDD-deploy-10a]` | WP-8 |
| `[CD-CentralUI-1]` through `[CD-CentralUI-5]` | WP-9, WP-10, WP-11, WP-13 |
| `[CD-Health-1]` through `[CD-Health-6]` | WP-9 |
| `[CD-Sec-1]` through `[CD-Sec-4]` | WP-1 through WP-7, WP-10 |
| `[CD-Inbound-1]`, `[CD-Inbound-2]` | WP-5 |
| `[CD-Deploy-1]` through `[CD-Deploy-4]` | WP-7, WP-8 |

**Result**: No orphaned requirements. All checklist items map to work packages with acceptance criteria that would fail if the requirement were not implemented.

### Reverse Check (Work Packages → Requirements)

Every work package traces to at least one requirement or design constraint:

| Work Package | Requirements/Constraints |
|-------------|-------------------------|
| WP-1 | `[8-site-1]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[KDD-ui-1]` |
| WP-2 | `[8-site-2]`, `[CD-CentralUI-2]`, `[CD-Sec-1]`, `[KDD-ui-1]` |
| WP-3 | `[8-area-1]`, `[8-area-2]`, `[3.10-ui-1]`, `[3.10-ui-2]`, `[3.10-ui-4]`, `[KDD-ui-1]` |
| WP-4 | `[8-ldap-1]`, `[8-ldap-2]`, `[CD-Sec-1]`, `[KDD-ui-1]` |
| WP-5 | `[7.2-1]` through `[7.2-5]`, `[8-apikey-1]` through `[8-apikey-4]`, `[CD-Inbound-1]`, `[CD-Inbound-2]`, `[KDD-ui-1]` |
| WP-6 | `[8-inst-1]`, `[8-inst-5]`, `[8-area-3]`, `[3.10-ui-3]`, `[CD-Sec-2]`, `[CD-Sec-4]`, `[KDD-ui-1]` |
| WP-7 | `[8-inst-2]` through `[8-inst-4]`, `[3.8.1-ui-1]` through `[3.8.1-ui-3]`, `[CD-Deploy-2]` through `[CD-Deploy-4]`, `[KDD-ui-1]` |
| WP-8 | `[8-deploy-1]`, `[8-deploy-2]`, `[KDD-ui-2b]`, `[KDD-deploy-10a]`, `[CD-Deploy-1]`, `[KDD-ui-1]` |
| WP-9 | `[8-health-1]` through `[8-health-7]`, `[11-ui-1]` through `[11-ui-7]`, `[KDD-ui-2a]`, `[KDD-ui-3a]`, `[CD-Health-1]` through `[CD-Health-6]`, `[KDD-ui-1]` |
| WP-10 | `[CD-CentralUI-2]`, `[CD-Sec-1]` through `[CD-Sec-3]`, `[KDD-ui-1]` |
| WP-11 | `[KDD-ui-1]`, `[CD-CentralUI-3]`, `[KDD-sec-4a]` |
| WP-12 | `[13.1-ui-1]`, `[KDD-ui-1]` |
| WP-13 | `[CD-CentralUI-4]`, `[8-apikey-4]`, `[KDD-code-1]`, `[KDD-code-2]` |

**Result**: No untraceable work packages. All map to requirements or design constraints.

### Negative Requirement Check

| Negative Requirement | Acceptance Criterion | Verification |
|---------------------|---------------------|--------------|
| Non-Admin cannot access Admin pages | WP-10: unauthorized page shows access denied. Test: Deployment user navigates to site management, gets denied. | Sufficient |
| Site-scoped Deployment cannot act outside permitted sites | WP-6, WP-7: scoped users see/act only on permitted sites. Test: scoped user cannot see or act on other sites' instances. | Sufficient |
| Cannot disable already-disabled instance | WP-7: button disabled per state transition matrix. Test: disable button not available for disabled instance. | Sufficient |
| Cannot enable a not-deployed instance | WP-7: button disabled per state transition matrix. Test: enable button not available for not-deployed instance. | Sufficient |
| Cannot delete instance if site unreachable | WP-7: delete fails with clear error. Test: site offline, delete returns error. | Sufficient |
| S&F messages not cleared on deletion | WP-7: UI does not imply messages are cleared. Test: UI confirmation dialog text does not mention message clearing. | Sufficient |
| No live machine data visualization | WP-9 `[CD-CentralUI-1]`: health dashboard is display-only for management metrics. No machine data pages exist. | Sufficient — absence verified by navigation check. |
| No alerting on health status | WP-9 `[CD-Health-5]`: health monitoring is display-only. No notification or alert configuration exists. | Sufficient — absence verified by feature check. |

**Result**: All negative requirements have explicit acceptance criteria that would catch violations.

---

## Codex MCP Verification

**Status**: Pass with corrections.

**Step 1 — Requirements coverage review**: Codex (gpt-5.4) reviewed the complete plan against source documents. Findings and resolutions:

1. **`[CD-Sec-1]` and `[CD-Sec-2]` overstated**: Codex noted the plan traces these constraints but does not implement all permissions listed (system config, audit log viewer, deploy action, debug view, etc.). **Resolution**: Added phase-split annotations to `[CD-Sec-1]` and `[CD-Sec-2]` in the Design Constraints Checklist clarifying which permissions are Phase 4 vs. Phase 5/6. The constraints are correctly traced for the Phase 4 portion.

2. **`[8-area-3]` area assignment not covered by WP-6**: Codex noted WP-6 only filters by area but does not assign areas. **Resolution**: Clarified in the requirements checklist that area assignment during instance creation is a Phase 5 concern. Phase 4 covers area as a display/filter field. The requirement is split-covered across phases.

3. **`[KDD-sec-4a]` failover coverage**: Codex noted shared Data Protection keys and JWT infrastructure are not covered. **Resolution**: Added clarification to WP-11 that Data Protection keys and JWT are Phase 1 infrastructure; Phase 4 covers the UI-side reconnection behavior. No gap — the constraint is split across phases.

4. **Monotonic sequence numbers not explicitly covered**: Codex noted health report monotonic sequence numbers and stale-report rejection are not in WP-9. **Resolution**: Dismissed — monotonic sequence numbers and stale-report rejection are Phase 3B backend concerns (central-side aggregation logic). The UI displays whatever the aggregation layer provides. No UI-specific acceptance criterion needed.

5. **`[KDD-ui-1]` Bootstrap-only constraint not explicitly verified**: **Resolution**: Added explicit acceptance criterion to WP-11 requiring Bootstrap CSS only, no third-party component frameworks, custom Blazor components only.

6. **WP-5 `[7.2-1]` storage location not verified in ACs**: **Resolution**: Added explicit AC to WP-5: "API keys are persisted to the configuration database (verified by integration test)."

7. **WP-7 disable ACs too vague**: **Resolution**: Strengthened WP-7 disable AC to explicitly mention stopping data subscriptions, script triggers, and alarm evaluation while retaining deployed configuration.

8. **`[CD-Deploy-4]` "not marked as deleted until site confirms"**: **Resolution**: Dismissed for Phase 4 — this is backend behavior enforced by the Deployment Manager in Phase 3C. The UI AC covers showing the error when site is unreachable and the instance remaining in its current state. The "not marked as deleted" guarantee is a backend invariant, not a UI concern.

9. **`[CD-Health-1]` in-memory storage not verified**: **Resolution**: Dismissed — in-memory storage is a Phase 3B backend architectural decision. The UI AC verifies "current/latest only" display which is the observable consequence.

10. **`[CD-CentralUI-1]` no machine data not explicitly verified**: **Resolution**: Added explicit AC to WP-9: "No live machine data visualization anywhere in Phase 4 pages."

**Step 2 — Negative requirement review**: All negative requirements have acceptance criteria that would catch violations. No findings.

**Step 3 — Split-section gap review**: Section 8 split across Phases 4/5/6 covers all workflows. No unassigned or double-assigned bullets found.
