Hub stage 3: compare and sync app configs across servers

The hub keeps a baseline per app in /data/apps/<app>/baseline.json. Local
fields (overrides.json) are left out of the sync and out of the matrix
comparison. Each server gets the baseline plus its own values.

Applying goes target picker, preview with per-server diffs and warnings,
then apply. Apply refuses a server whose config changed since the
preview, saves the old config to history, then reads the new one back
to check it.

Large config bodies are read only for signed-in callers. The App config
dialog has Compare, Baseline and Local fields tabs and an empty state
that offers an import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DenozordecandClaude Opus 5.5 committed 2026-10-31 16:46:15 +07:00
1 parent 6acd2d656d
commit 0e05039202
22 files changed
+2434 -58

No files matched your search

+1 -1
View File
@@ -63,7 +63,7 @@ export class Upstream {
the outcome, what the hub remembers of this server is dropped afterwards, so the next read
shows the state the write left. `body` is a multipart upload (the app zip).
*/
async write(server: HubServer, path: string, params: Params = {}, body?: FormData): Promise<unknown> {
async write(server: HubServer, path: string, params: Params = {}, body?: FormData | URLSearchParams): Promise<unknown> {
if (server.adminToken === undefined) throw new UpstreamError('rejected', 'no admin token configured')
try {
const init: RequestInit = body === undefined ? { method: 'POST' } : { method: 'POST', body }