# Nexus Remote Foundation 1.0 — Evidence Summary

> Build **87** · Version `0.1.0-identity2` · 2026-06-05  
> Scope: **Device visibility only** — presence, online status, health feed. **No remote control.**

## Executive summary

Nexus Remote Foundation 1.0 adds end-to-end device visibility: agents dispatch heartbeats every 30 seconds, the Identity API persists presence and heartbeat history, and Control Center Settings shows online/offline/warning/critical counts plus a device list. POC uses HTTP polling (45s); SignalR/WebSocket interfaces are documented for a future phase.

## What was built

### Agent (`NexusShell/Agent/`)

| Component | Role |
|-----------|------|
| `NexusPresenceService` | Local presence snapshot (user, org, online, last heartbeat) |
| `NexusDeviceStatusService` | Aggregates presence + health + versions |
| `NexusHeartbeatDispatcher` | Timer every **30s** → POST `/api/devices/heartbeat` |
| Agent endpoints | `GET /agent/presence`, `GET /agent/device-status` |

**Heartbeat payload:** DeviceId, User, Organization, AgentVersion, ShellVersion, Health, Online, Timestamp

### Backend (`NexusIdentity.Api`)

| Area | Deliverable |
|------|-------------|
| Entities | `DevicePresenceEntity`, `DeviceHeartbeatEntity`, `HealthStatus` enum |
| Migration | `20260605140000_RemoteFoundation` |
| Service | `DevicePresenceService` — offline if no heartbeat within **90s** (configurable) |
| Presence API | `GET /api/presence`, `POST /api/presence` |
| Device status API | `GET /api/devices/status`, `GET /api/devices/online` |
| Heartbeat | Extended `POST /api/devices/heartbeat` writes presence + heartbeat feed |

### Control Center UI (Settings → Control Center)

- Online / Offline / Warning / Critical counters
- Device list: Name, Owner, Organization, Online, Health, Version, Last Seen
- Remote API when `ControlCenter:BaseUrl` configured; local agent fallback
- POC polling every **45s** while section is open

## Heartbeat model

```
Agent (30s timer)
  → NexusHeartbeatDispatcher
  → POST /api/devices/heartbeat
  → DeviceEntity.LastSeenUtc, Online, LastHealth
  → DevicePresenceEntity (latest snapshot)
  → DeviceHeartbeatEntity (health feed row)
```

## Online / offline model

| Rule | Value |
|------|-------|
| Agent dispatch interval | 30 seconds |
| Offline threshold | 90 seconds (`Nexus:Presence:OfflineThresholdSeconds`) |
| Logic | `IsOnline = LastSeenUtc within threshold AND last heartbeat reported Online=true` |
| Stale devices | HealthStatus → `Offline` |

Configure in Identity API `appsettings.json`:

```json
"Nexus": {
  "Presence": {
    "OfflineThresholdSeconds": 90
  }
}
```

## Realtime plan (future)

POC uses `INexusControlCenterPresencePoller` (HTTP poll). Future transport:

```csharp
public interface INexusControlCenterRealtimeChannel
{
    event EventHandler<NexusControlCenterPresenceSummary>? PresenceUpdated;
    Task ConnectAsync(CancellationToken ct = default);
    Task DisconnectAsync(CancellationToken ct = default);
}
```

**Phase 2:** SignalR hub `PresenceHub` with `DevicePresenceChanged` events; shell implements `INexusControlCenterRealtimeChannel` and retires poller.

## API list (new)

| Method | Route | Description |
|--------|-------|-------------|
| GET | `/api/presence` | Presence summary + device rows |
| POST | `/api/presence` | Upsert presence (same payload as heartbeat) |
| GET | `/api/devices/status` | Full device status dashboard |
| GET | `/api/devices/online` | Online devices subset |

Extended: `POST /api/devices/heartbeat` now accepts User, Organization, Timestamp.

## Constraints honored

- No remote control, screen sharing, or deployment execution
- No registry or secrets changes
- No git commit

## Build status

| Project | Result |
|---------|--------|
| `NexusIdentity.Api` | PASS (Release) |
| `NexusShell` | PASS (Release) |

## Screenshots

See `SCREENSHOT-NOTES.md` for capture steps:

- `presence-dashboard.png` — Control Center presence counters
- `online-devices.png` — Online count + device list
- `device-status.png` — Health/version/last seen columns

## Changed files (summary)

**Contracts:** `DeviceHeartbeatRequest.cs`, `HealthStatus.cs`

**Identity API:** `PlatformEntities.cs`, `HealthStatus.cs`, `IdentityDbContext.cs`, migration, `DevicePresenceService.cs`, `PresenceController.cs`, `DevicesController.cs`, `Program.cs`, `appsettings.json`

**Shell Agent:** `NexusPresenceService.cs`, `NexusDeviceStatusService.cs`, `NexusHeartbeatDispatcher.cs`, `NexusAgentService.cs`, `NexusAgentConfig.cs`, `App.xaml.cs`

**Shell Control Center:** `NexusControlCenterRealtimeModels.cs`, `NexusControlCenterApiClient.cs`, `NexusControlCenterService.cs`, `NexusSettingsViewModel.cs`, `NexusSettingsView.xaml`, `version.poc.json`

**Evidence:** this SUMMARY, `SCREENSHOT-NOTES.md`
