# Link'd DMR CPS

Link'd DMR Customer Programming Software is a Windows desktop environment for creating, validating, backing up, and programming the Link'd app RF codeplug on a CJ-1. It connects through an authorized Android Debug Bridge (ADB) session and the app's narrow CPS bridge. This is app-owned RF-codeplug access, not direct RF-module or firmware readback.

## Features

- Compact CPS 2.0-style desktop workflow with original Link'd branding, a hierarchical category tree, breadcrumbs, full-width programming panes, validation dock, log, and radio status bar.
- Versioned `.ldcp2` codeplug with strict JSON parsing and unknown-field rejection.
- Import from and export to the Android app's existing schema-4 `.linkd.json` codeplug format.
- RF-codeplug programming for profiles, zones, RF channels, contacts, RX groups, and scan lists.
- Local `.ldcp2` planning for Cellular PTT, selector behavior, voice announcements, sounds, radio lock, Enhanced Privacy references, and programmable buttons; these remain app/device-owned rather than being falsely reported as RF-codeplug writes.
- Automatic validation with exact navigation paths and recommended corrections.
- Undo/redo, validation navigation, full clone, identity-preserving Smart Clone, and codeplug comparison.
- A full-width Zones → Channels → Channel Editor workflow. Select a zone, open its channel list, then open one complete General or RX/TX channel record with zone, mode, RF, contact, scan, privacy, admit, timeout, and favorite controls.
- MOTOTRBO-style operation feedback through original Link'd progress windows for Read, Write, verified completion, safe cancellation, and mandatory recovery.
- Filter-aware bulk channel editing and reference-safe deletion in local CPS files.
- Scan-list membership and Priority 1/Priority 2 editing.
- Website-aligned Link'd waveform icon, Windows multi-size app icon, maximized desktop startup, and per-monitor high-DPI support.
- Persistent local backend for recent codeplugs, automatic restore points, and durable programming receipts.
- Strict CJ-1 detection that does not accept an unrelated Android phone as a radio.
- Read and write of the Link'd app's non-secret RF codeplug through its dedicated CPS bridge.
- Atomic codeplug saves and automatic pre-write backups.
- Token-bound finalize/rollback: a write is not declared complete until app read-back verifies and the provider issues a terminal receipt.
- A visible **Recover Transaction** action safely rebinds to the same CJ-1 after a USB interruption; the app blocks radio startup and automatically restores an unresolved transaction on startup or expiry.
- Original Link'd visual language; no Motorola artwork or copied interface assets.

## CJ-1 connection boundary

The CPS bridge exposes only the Link'd app's non-secret **RF codeplug**: profile, zones, RF channels, contacts, RX groups, and scan lists. It has no raw radio-command, firmware, flashing, recording, archive, credential, or privacy-key endpoint. Before programming, CPS asks the Link'd app to release PTT, unkey, disconnect, and stop its radio service through the app's normal safety path. The bridge rechecks both service ownership and controller readiness before any codeplug mutation; if either remains active, programming is refused without changing settings. The bridge supports Low and High transmit power; Medium is rejected instead of being silently converted.

The current bridge supports adding and editing RF-codeplug records. It deliberately refuses to delete records that already exist in the Link'd app, because those records may carry app-only fields that CPS cannot see. Delete an existing app record on the CJ-1 itself; deleting items in an offline `.ldcp2` file remains supported. CPS displays the exact connected app package and refuses to continue if multiple Link'd app variants are installed.

Selector behavior, voice announcements, sound profiles, privacy persistence, radio lock, physical-button assignments, and Cellular PTT/account groups are not part of Android RF-codeplug schema 4. CPS keeps them in the local `.ldcp2` plan, labels them as app/device settings, and refuses to claim that an RF-codeplug transaction programmed them.

Enhanced Privacy key material never leaves the device. CPS can carry non-secret profile labels and key-slot references, but privacy assignments must be confirmed on the CJ-1 after programming.

## Recording and secret boundary

Owner-only recordings are not part of the CPS codeplug or programming transport. The bridge exposes no API to browse, read, export, clone, delete, write, inspect, or hash recordings or archives. It likewise exposes no credential, local-secret, or privacy-key API. The serializer rejects those fields if they are placed in a codeplug file.

This boundary keeps recording storage outside the operation entirely; CPS does not prove safety by opening or calculating a digest of private recordings.

## Run

```powershell
dotnet run --project .\src\LinkdDmr.Cps.App\LinkdDmr.Cps.App.csproj
```

Connect the CJ-1 directly by USB with its Link'd app installed, authorize this computer if Android asks, then choose **Radio → Connect to Link'd app on CJ-1**. **Read RF Codeplug** imports the app-owned RF codeplug and shows each read/verification phase in a dedicated progress window. **Write RF Codeplug** safely stops the active radio path, performs preflight validation, saves a backup, applies only that RF codeplug under an app-owned transaction fence, reads it back through the transaction-bound URI, and finalizes only after verification. If USB is interrupted at the receipt boundary, reconnect the same CJ-1 and choose **Recover Transaction**; CPS never guesses whether a write succeeded.

The CPS never selects an attached phone or tablet as a CJ-1. Bootloader, preloader, recovery, and firmware interfaces are outside its supported connection path.

The offline backend stores its operational state under `%LOCALAPPDATA%\LinkdDMR\CPS`. It is deliberately local so opening, validating, backing up, restoring, and programming a radio never depends on the website being available.

## Verify

```powershell
dotnet build .\LinkdDmr.Cps.sln -c Release
dotnet run --project .\tests\LinkdDmr.Cps.Verification\LinkdDmr.Cps.Verification.csproj -c Release
```

The verification executable checks the sample codeplug, strict protected-data rejection, preservation flags, atomic file round-trip, Android compatibility, and isolated safe-programming transaction behavior.

## Package a Windows release

```powershell
.\tooling\publish.ps1
```

The packaging script runs verification, publishes a self-contained Windows x64 build, bundles only the ADB files needed by the supported companion connection, performs a clean-start smoke check, and writes the portable folder, ZIP, signing status, and SHA-256 manifests to `outputs\linkddmr-cps-current`.
