Hub stage 8: settings drift, webhook notices, profiles
The drift check now also covers the settings baseline and the Blocked and Allowed lists baseline; the drift dialog offers Open compare, Accept as baseline and Revert to baseline for them. Old drift.json files still load. HUB_WEBHOOK_URL (and an optional HUB_WEBHOOK_SECRET for an HMAC signature) receives drift.found, drift.cleared and write.failed notices, only on change, without values, never blocking a request and never logging the address beyond its host. Admins see the webhook status and can send a test from About and from the drift dialog. Profiles bundle the hub's app, settings and lists baselines. Applying one to a server runs install, app configs, settings and lists in order after a preview; a failed step stops that server's later steps and Retry failed resumes from it. Profiles export and import as a file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
392b644faa
commit
9742f0fe69
32 files changed
+3123
-106
No files matched your search
+5
-4
@@ -286,9 +286,9 @@ export class AppsConfig {
|
||||
return importLocalValues(Object.fromEntries([...live].map(([id, l]) => [id, l.installed && l.ok ? l.text : null])), paths)
|
||||
}
|
||||
|
||||
async preview(name: string, ids: string[]): Promise<{ targets: TargetPreview[] }> {
|
||||
async preview(name: string, ids: string[], overrideText?: string): Promise<{ targets: TargetPreview[] }> {
|
||||
const targets = this.#targets(ids)
|
||||
const baseline = this.getBaseline(name)
|
||||
const baseline = overrideText === undefined ? this.getBaseline(name) : ({ app: name, text: overrideText, updatedAt: '', updatedBy: '' } satisfies Baseline)
|
||||
if (baseline === null) throw new UserError('This app has no baseline yet. Import one from a server first.')
|
||||
const overrides = this.getOverrides(name)
|
||||
const live = await this.#liveAll(name, true)
|
||||
@@ -368,8 +368,9 @@ export class AppsConfig {
|
||||
return { results: done.map((d) => d.result), details }
|
||||
}
|
||||
|
||||
async apply(name: string, ids: string[], expect: Record<string, string>): Promise<{ results: TargetResult[]; details: Record<string, string> }> {
|
||||
const baseline = this.getBaseline(name)
|
||||
/* `overrideText` is a config that is not the hub's baseline (a profile's). The server's local values still apply. */
|
||||
async apply(name: string, ids: string[], expect: Record<string, string>, overrideText?: string): Promise<{ results: TargetResult[]; details: Record<string, string> }> {
|
||||
const baseline = overrideText === undefined ? this.getBaseline(name) : ({ app: name, text: overrideText, updatedAt: '', updatedBy: '' } satisfies Baseline)
|
||||
if (baseline === null) throw new UserError('This app has no baseline yet. Import one from a server first.')
|
||||
const overrides = this.getOverrides(name)
|
||||
return this.#applyMany(name, ids, (s) => () => effectiveConfig(baseline.text, overrides, s.id).text, expect)
|
||||
|
||||
Reference in new issue
Block a user