54 desktop app - #57
Merged
Merged
Conversation
Approved 2026-05-18. Covers multi-project data model, per-project relay isolation, persistent boss identity, and the bugs that depend on (or were unblocked by) the refactor: black-screen nav, chat overflow, "unknown" agent labels, missing comments after submit, peer ID in My Activity, AgentFM title centering. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
27 task-by-task plan against the 2026-05-18 spec. TDD where applicable, exact code in every step, one commit per task. Boss identity risk resolved during planning (already persistent on the Go side). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Snapshot of the desktop app source as it stands before the Phase 1 project-model refactor. Future task commits will diff cleanly against this baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…able Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sets BrowserWindow icon and app.dock.setIcon (macOS) from the AgentFM logo so the running app shows the real icon instead of the default Electron icon; bundles build/icon.png as an extra resource for the packaged dock icon. The .icns baked into the .app already drives the Finder/dock/menu icon for the installed executable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…'t Unknown The Assets tab showed 'Unknown agent' for any artifact whose .meta.json sidecar was missing — which happened for every non-desktop dispatch (CLI, direct /api/execute, SDK) and any desktop dispatch whose renderer completion path was interrupted. Root cause: identity was captured post-hoc by the renderer, not at the source. The boss already knows the producing worker at dispatch time (expectArtifact(taskID, peerID) + activeWorkers/lastProfile). Write the identity sidecar (agentName/agentDescription/agentPeerId) there, covering all four dispatch paths (sync, async, TUI, chat). The renderer sidecar still layers on prompt/projectName for desktop dispatches. Not offline-related: sidecars that existed always carried the name regardless of the agent's online state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clicking History on a peer with zero ledger entries crashed the view
with 'Cannot read properties of null (reading filter)'. Root cause:
GatherPeerEntries returns a nil slice for an empty log, and Go's
json.Marshal emits a nil slice as null, so /v1/peers/:id/log returned
{"entries":null}; PeerView then called .filter on null.
Defense in depth:
- API contract: handleLog now returns entries:[] (never null).
- Client: PeerView guards log.entries ?? [] so any null is tolerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oped boot - Star ratings in PeerView summary (overall) + every rating entry, which the Activity tab shares via EntryRow. - Peer digest shown in full and click-to-copy (was truncated). - Fix offline-agent inconsistency: the initial backend boot now scopes to the ACTIVE project's ledger/relay/swarmKey (previously it booted against the global default ledger, showing a pile of unrelated historical subjects until you switched projects). main.ts reads the active project from settings and mirrors switchProject's config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…esh boss Strengthens the single-entry witness acceptance test: a boss authors a batch of distinct ratings, a witness ingests them all via gossip, every boss goes offline, then a brand-new boss with an EMPTY ledger recovers the COMPLETE history from the witness alone via CatchUpInbox. Passes -race. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds build/icon.ico (generated from the AgentFM logo) and a windows-latest CI workflow that cross-builds the Windows Go backend, builds the renderer, and produces the NSIS installer natively (no wine). The Windows app packages fine from macOS (dist/win-unpacked runs), but the NSIS .exe installer + exe icon-stamp require wine, which is broken on this host — so the installer is built on a Windows runner instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Offline 'agents' with no resolvable name/description were rated peer-IDs the boss never observed via telemetry — agent names/descriptions come only from live WorkerProfile broadcasts, never the ledger, so there is nothing to show for them. They rendered as nameless peer-ID cards. Radar now only shows an offline agent if it has a resolvable identity (name/capability/image from the API or the persisted peer-identity cache). Agents actually seen online keep their name+description while offline; pure trust-graph subjects are no longer surfaced as agents. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CRITICAL: acceptLocalAlert accepted two heads at DIFFERENT tree sizes as a 'conflict', so any peer could replay two of a victim's normal, validly -signed heads (routine log growth) to permanently brand them an equivocator mesh-wide — a hard, unrecoverable dispatch ban. A genuine equivocation is same TreeSize + different RootHash (a fork an honest peer never produces); different sizes are now rejected. Test proves the framing attack is refused while genuine equivocation still marks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HIGH: CatchUp (own-log catch-up vs the relay at boss startup) lacked the non-advancing-cursor guard its sibling CatchUpInbox has, ran with context.Background(), and had no ctx.Done() in the loop — a malicious relay signing a huge-TreeSize head and serving non-advancing full pages livelocked the startup goroutine forever. Adds the progress guard + ctx.Done() and bounds the bootstrap call with a 2-minute timeout. Test proves it terminates in ~ms instead of spinning to the ctx deadline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
HIGH (defense-in-depth): killStaleOnPort string-interpolated an uncoerced apiPort into an execSync shell command; electron-store has no runtime schema and the settings:set/backend:restart IPC accepted any value, so a compromised renderer could inject shell commands into the main process. Adds sanitizePort (validated 1-65535 integer), guards the execSync sink with it, and validates apiPort at the IPC boundary. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M6: no rater!=subject guard let an already-trusted peer self-rate to amplify its own honesty score. M5: a NaN/Inf score reaching the engine propagated through the clamp (NaN comparisons are false), bypassing the trust gate. ingest now skips self-edges and non-finite scores. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A uint64 offset that overflows int became negative, and all[offset:] panicked (slice bounds [-1:]). Offset is now clamped to a non-negative bounded int. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t M1) /api/relay/test dialed any multiaddr, an SSRF port-scan oracle when the API is exposed off-host. It now refuses private (RFC1918/ULA), link-local, unspecified and multicast ranges while still allowing loopback (the desktop's local relay) and public relays. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The token-less loopback boss served POSTs with a wildcard CORS policy, so any web page the user visited could drive /api/execute (CSRF). Unsafe methods now require an allowed Origin: absent, 'null' (Electron file://), file:, or a loopback host. Cross-site browser origins are refused 403; GET/HEAD are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GET /v1/peers/{id}/reputation ran a full O(ledger) EigenTrust recompute
per request; a burst amplified into heavy CPU. Recompute is now throttled
to once per second, so concurrent reads coalesce.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… release script - README: simpler star-worthy main page led by the desktop app, 4 screenshots (radar/chat/history/assets), trimmed quick start, docs table. - docs/DESKTOP.md: install + feature tour + CLI/API mapping. - docs/http-api.md: add the remaining endpoints (relay/test, about, events, comments/self, comments/:cid[.json], peer summary, /log entry_hash). - scripts/release.sh: cross-compile agentfm + relay for 4 platforms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.