feat(FN-3707): implement mesh auth snapshot replication across core, engine
The merge delivers two major features: mesh auth snapshot synchronization across nodes (FN-3707 steps 2/4/5, including core types, central-core plumbing, peer-exchange updates, and settings/node sync route helpers) and a bundled roadmap plugin with chat UX improvements (FN-3162, FN-3756, FN-3771, FN Fusion-Task-Id: FN-3707
This commit is contained in:
@@ -2917,12 +2917,22 @@ describe("CentralCore", () => {
|
||||
const legacy = await syncCentral.getSettingsForSync({});
|
||||
const snapshot = await syncCentral.getProjectSettingsSnapshot({});
|
||||
const result = await syncCentral.applyProjectSettingsSnapshot(snapshot);
|
||||
const authSnapshot = syncCentral.getAuthMaterialSnapshot({ foo: { providerId: "foo", accountLabel: "acct" } as any });
|
||||
const authSnapshot = syncCentral.getAuthMaterialSnapshot({
|
||||
foo: {
|
||||
type: "oauth",
|
||||
accessToken: "access-token",
|
||||
refreshToken: "refresh-token",
|
||||
expires: Date.now() + 60_000,
|
||||
accountId: "acct",
|
||||
},
|
||||
});
|
||||
|
||||
expect(snapshot.payload.global).toEqual(legacy.global);
|
||||
expect(snapshot.payload.projects).toEqual(legacy.projects);
|
||||
expect(typeof result.success).toBe("boolean");
|
||||
expect(syncCentral.applyAuthMaterialSnapshot(authSnapshot).foo.providerId).toBe("foo");
|
||||
const authApplyResult = syncCentral.applyAuthMaterialSnapshot(authSnapshot);
|
||||
expect(authApplyResult.authCount).toBe(1);
|
||||
expect(authApplyResult.providerAuth.foo.accountId).toBe("acct");
|
||||
} finally {
|
||||
await syncCentral.close();
|
||||
rmSync(tempDir + "-snapshot", { recursive: true, force: true });
|
||||
|
||||
@@ -56,7 +56,16 @@ describe("shared-mesh-state", () => {
|
||||
const activitySnapshot = createActivityLogSnapshot([], exportedAt);
|
||||
const auditSnapshot = createRunAuditSnapshot([], exportedAt);
|
||||
const settingsSnapshot = createProjectSettingsSnapshot({ global: {} }, exportedAt);
|
||||
const authSnapshot = createAuthMaterialSnapshot({}, exportedAt);
|
||||
const authSnapshot = createAuthMaterialSnapshot({
|
||||
anthropic: { type: "api_key", key: "sk-ant" },
|
||||
"openai-codex": {
|
||||
type: "oauth",
|
||||
accessToken: "access-token",
|
||||
refreshToken: "refresh-token",
|
||||
expires: 1_900_000_000_000,
|
||||
accountId: "acct-1",
|
||||
},
|
||||
}, exportedAt);
|
||||
|
||||
for (const snapshot of [
|
||||
taskSnapshot,
|
||||
|
||||
@@ -3171,9 +3171,14 @@ export class CentralCore extends EventEmitter<CentralCoreEvents> {
|
||||
return createAuthMaterialSnapshot(providerAuth);
|
||||
}
|
||||
|
||||
applyAuthMaterialSnapshot(snapshot: AuthMaterialSnapshot): Record<string, ProviderAuthEntry> {
|
||||
applyAuthMaterialSnapshot(snapshot: AuthMaterialSnapshot): { success: true; authCount: number; providerAuth: Record<string, ProviderAuthEntry> } {
|
||||
validateSnapshotEnvelope(snapshot);
|
||||
return { ...(snapshot.payload.providerAuth ?? {}) };
|
||||
const providerAuth = { ...(snapshot.payload.providerAuth ?? {}) };
|
||||
return {
|
||||
success: true,
|
||||
authCount: Object.keys(providerAuth).length,
|
||||
providerAuth,
|
||||
};
|
||||
}
|
||||
|
||||
// ── Settings Sync API ─────────────────────────────────────────────────
|
||||
|
||||
@@ -2829,6 +2829,12 @@ export interface ProviderAuthEntry {
|
||||
key?: string;
|
||||
/** OAuth access token (for "oauth" type). Omitted for API key providers. */
|
||||
accessToken?: string;
|
||||
/** OAuth refresh token (for "oauth" type). */
|
||||
refreshToken?: string;
|
||||
/** OAuth credential expiry epoch milliseconds. */
|
||||
expires?: number;
|
||||
/** Optional OAuth account identifier. */
|
||||
accountId?: string;
|
||||
/** Whether this credential has been validated. */
|
||||
authenticated?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user