# Nexus update manifest schema (`latest.json`)

Canonical channel file served at `https://nexus.ninjakernen.info/downloads/latest.json`.

## Required fields (v1)

| Field | Type | Description |
|-------|------|-------------|
| `build` | int | Monotonic build number used for upgrade comparison |
| `version` | string | Human-readable version label (e.g. `0.1.0-identity3`) |
| `artifact` | object | Primary package descriptor |
| `artifact.url` | string | HTTPS URL to `nexus-shell-poc.zip` |
| `artifact.sha256` | string | Lowercase hex SHA256 of the ZIP |
| `artifact.sizeBytes` | long | ZIP size in bytes |
| `minimumSupportedBuild` | int | Client must be ≥ this build to apply the update |
| `mandatory` | bool | Reserved; not enforced in POC |
| `notes` | string[] | Release notes shown in Update UI |

## Backward compatibility

Clients also accept legacy flat fields from build ≤87 manifests:

| Legacy field | Maps to |
|--------------|---------|
| `packageUrl` | `artifact.url` |
| `sha256` | `artifact.sha256` |
| `sizeBytes` | `artifact.sizeBytes` |
| `releaseNotes` | `notes` |
| `minimumSupportedVersion` | Informational only; `minimumSupportedBuild` is authoritative |

Publish scripts write **both** canonical and legacy fields so older and newer clients work.

## Example (build 88)

```json
{
  "product": "Ninja Nexus",
  "channel": "poc",
  "version": "0.1.0-identity3",
  "build": 88,
  "publishedAt": "2026-06-05T20:00:00Z",
  "minimumSupportedBuild": 1,
  "artifact": {
    "url": "https://nexus.ninjakernen.info/downloads/releases/0.1.0-identity3/nexus-shell-poc.zip",
    "sha256": "<hex>",
    "sizeBytes": 15300000
  },
  "packageUrl": "https://nexus.ninjakernen.info/downloads/releases/0.1.0-identity3/nexus-shell-poc.zip",
  "sha256": "<hex>",
  "sizeBytes": 15300000,
  "notes": ["Auto-update smoke build"],
  "releaseNotes": ["Auto-update smoke build"],
  "mandatory": false
}
```

## Client behaviour

1. Fetch `latest.json` at startup and on manual check.
2. Compare `build` against `config/version.poc.json`.
3. Reject if `currentBuild < minimumSupportedBuild`.
4. Download ZIP to `%TEMP%`, verify SHA256 against `artifact.sha256` (or `sha256`).
5. Apply via `apply-pending-update.ps1` after user confirmation (POC).

Logs: `%LocalAppData%\NinjaNexus\logs\update.log`
