Skip to content

Keep desktop peer previews separate from verified machines - #44

Merged
JaredP94 merged 3 commits into
mainfrom
feat/desktop-peer-verification
Nov 3, 2026
Merged

JaredP94 merged 3 commits into
mainfrom
feat/desktop-peer-verification

Conversation

@JaredP94

@JaredP94 JaredP94 commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Description

Adopt the peer provenance published by #43 in the desktop without treating a public UUID claim as a peer identity.

  • One shared TypeScript nodeRecordKey mirrors Go DirectoryNode.RecordKey() exactly. Local/verified records use hostUuid except reserved prefixes; every other record requires a preview: / manual: peerRecordId. Empty keys are dropped. A verified proof binding is never used as a host id.
  • Normalize bridge and renderer collections, keeping previews independent even when their UUID, name, address and timestamps match a proven peer. Remove desktop address/name/age collapse; broker snapshots own identity and lifetime. Proxy events enrich established peers only and cannot resurrect withdrawn records.
  • Node cards, tray rows and available-node lists show Not in your cluster with Pair using the existing PIN exchange by address, or Engine only — added by address without PAIR peer controls/telemetry. Local/verified peer presentation is retained. Missing verification never produces a guessed update recommendation.
  • TUI provenance wording matches the desktop, including treating missing verification as unverified.

Scope

Desktop projection, shared additive types/helper, renderer stores/cards/lists, regression tests, component documentation, and TUI label alignment. No Go producer or JSON-RPC payload changes; generated desktop/docs/services-api.md is unchanged.

NodeItem and AvailableNode gain optional hostUuid, peerRecordId and identityVerification fields. These type changes are additive for the concurrent manual-nodes work. Its owned AddNodeModal.tsx, manual-node bridge/store, manual settings UI and Go manual-nodes code are untouched; that agent was informed of the canonical keys and copy.

Audit: membership, React keys, focus/selection, engine/model state, workload attribution and metric lookup use canonical record ids. Preview/manual cards never mount peer-only controls or telemetry. The desktop exposes no scheduler-priority, workload-targeting or proxy-node-selection action; those policies remain in Go. Pairing accepts an address, not a record selector; no claimed host UUID is sent for previews.

Version decision: retain main's existing unreleased nvpair-tui 1.2.1 patch bump (released v0.8.0 had 1.2.0). Shared Go changes are test-only. No other service compiled output or desktop release version changes.

Validation

macOS arm64, isolated worktree /tmp/pair-work/desktop-peer-verification, based on origin/main ad5edd7. Own npm ci --no-audit --no-fund; no shared/symlinked dependencies.

Passed:

  • npm run -s typecheck
  • npm run -s lint — zero warnings
  • npm run -s test:unit — 85 files, 844 tests
  • npm run -s dead-code:check — zero findings
  • npm run -s service-contracts:check — fresh, no unignored drift
  • npm run -s licenses:check — 296 dependencies attributed
  • In both services/shared and services/nvpair-tui: gofmt -l, go vet ./..., go test -count=1 ./..., GOOS=linux go vet ./..., GOOS=windows go vet ./...
  • node scripts/spdx-headers.mjs — 1282 checked, zero missing
  • git diff --check

Regression sensitivity:

  • New keying, broker-lifetime, store and rendering tests fail against the original desktop source: 13 failures. Restoring the fix returns the complete suite to green.
  • Replacing the canonical key helper with claimed-UUID fallback fails 14 of 18 shared fixture cases. Restored helper passes all cases; Go consumes the identical table and checks selector round trips.
  • Updated TUI provenance regression fails with the old wording, passes with the change.

Latest-head CI: run 41637002435, head 2bb42fc, all six jobs passed: Desktop checks, SPDX headers, Go modules on Linux/macOS, and cross-process tests on Linux/macOS. This is job-level CI evidence, not a claim that platform-skipped cases ran or that packaged/live deployments were exercised.

Risk

Desktop consumers now require canonical provenance from the upgraded broker. Older peer machines remain separately keyed previews until services can verify them; metadata does not identify why verification failed, so no upgrade diagnosis is guessed. Rows remain until the broker withdraws them instead of being hidden speculatively by desktop heuristics.

Live multi-node pairing, desktop launch, packaged artifacts and Windows runtime were not tested. No cross-process suite was run locally. Independent model review did not finish because the review tool timed out; the actual diff and required checks were reviewed locally.

Checklist

  • I have read the Contributing Guidelines.
  • Every commit is signed off (git commit -s), certifying the Developer Certificate of Origin.
  • New or existing tests cover the change.
  • Relevant documentation is updated.
  • I checked the diff, changed filenames, and commit messages for credentials, private data, internal URLs, internal issue identifiers, and generated artifacts.
  • I recorded the validation commands and results above.
  • I bumped any affected component in services/versions.json, and described user-visible changes above so they reach the release notes. (Existing sufficient unreleased TUI patch bump retained.)

Mirror DirectoryNode.RecordKey exactly in one shared helper and a fixture consumed by TypeScript and Go tests. Drop invalid records, isolate previews and manual configurations from claimed host UUIDs, and let broker discovery own record lifetime instead of collapsing by address, name or age. Proxy presence can enrich established peers but cannot create or resurrect identities.

Label unverified machines and address-added engines, start existing PIN pairing by address, and keep peer controls and telemetry out of preview and manual cards. Normalize renderer collections and preserve peer-keyed membership and workload attribution. Align TUI wording and document mixed-version behavior without guessing an upgrade diagnosis. Shared type additions are optional and no Go wire payload changes. Keep the already-unreleased TUI 1.2.1 patch bump relative to v0.8.0.

Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Review follow-up. The Add node modal's discovered list still showed "In
another cluster" and disabled Invite whenever a node reported
clustered: true, so an unauthenticated preview could hide pairing with a
public claim, and it keyed rows by node id rather than the record key.
It now matches the cluster settings list: rows are keyed by the record
key, labelled "Not in your cluster", and only previews get a Pair
action, by address through the PIN exchange. The shared rule is
canPairByAddress. A modal regression covers a clustered preview.

Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Review follow-up. The Add node modal regression removed its dialog stubs
and cleared the discovered-node store only after its assertions passed,
so a failure would leak them into later tests. The file's afterEach now
does both unconditionally.

Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
@JaredP94
JaredP94 merged commit b7be184 into main Nov 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant