merge: resolve v1.22.0 conflicts with custom

This commit is contained in:
2026-08-31 07:37:26 -04:00
200 changed files with 44922 additions and 775 deletions
@@ -214,7 +214,7 @@ Managed health failures are classified as `timeout`, `connection_refused`, `conn
- `createSettingsHelpers(dependencies)`: creates settings helper runtime for settings request/response shaping.
- Returned API:
- `normalizePwaAppName(value, fallback?)`
- `sanitizeSettingsUpdate(payload)`
- `sanitizeSettingsUpdate(payload)` — whitelist of persisted keys; includes `gitProviders` (validated via `packages/web/server/lib/git-providers/config.js` `sanitizeGitProviders`), which therefore round-trips through GET/PUT `/api/config/settings`.
- `mergePersistedSettings(current, changes)`
- `formatSettingsResponse(settings)`
@@ -5,7 +5,10 @@ import { registerWalkthroughRoutes } from '../walkthrough/routes.js';
import { registerSessionGoalRoutes } from '../session-goal/routes.js';
import { registerGitHubRoutes } from '../github/routes.js';
import { registerLinearRoutes } from '../linear/routes.js';
import { registerGitLabRoutes } from '../gitlab/routes.js';
import { registerGiteaRoutes } from '../gitea/routes.js';
import { registerGitRoutes } from '../git/routes.js';
import { registerGitProviderRoutes } from '../git-providers/routes.js';
import { registerDevServerRoutes } from '../dev-servers/routes.js';
import { registerMagicPromptRoutes } from '../magic-prompts/routes.js';
import { registerSessionFoldersRoutes } from '../session-folders/routes.js';
@@ -302,6 +305,9 @@ export const createFeatureRoutesRuntime = (dependencies) => {
registerSessionGoalRoutes(app);
registerGitHubRoutes(app);
registerLinearRoutes(app);
registerGitLabRoutes(app);
registerGiteaRoutes(app);
registerGitProviderRoutes(app);
registerGitRoutes(app);
registerDevServerRoutes(app, { scanner: devServerScanner, getOwnPorts });
registerMagicPromptRoutes(app, {
@@ -1,3 +1,4 @@
import { sanitizeGitProviders } from '../git-providers/config.js';
import { isAgentMemoryFeatureAvailable } from '../agent-memory/feature-flag.js';
export const createSettingsHelpers = (dependencies) => {
@@ -498,6 +499,10 @@ export const createSettingsHelpers = (dependencies) => {
const trimmed = candidate.gitModelId.trim();
result.gitModelId = trimmed.length > 0 ? trimmed : undefined;
}
const gitProviders = sanitizeGitProviders(candidate.gitProviders);
if (gitProviders) {
result.gitProviders = gitProviders;
}
if (typeof candidate.pwaAppName === 'string') {
result.pwaAppName = normalizePwaAppName(candidate.pwaAppName, undefined);
}
@@ -497,6 +497,46 @@ describe('settings helpers', () => {
expect(sanitized.favoriteModels).toEqual(payload.favoriteModels);
expect(sanitized.recentModels).toEqual(payload.recentModels);
});
it('round-trips a valid gitProviders payload through sanitizeSettingsUpdate', () => {
const helpers = createTestHelpersWithRealSanitizers();
const payload = {
gitProviders: {
github: { apiBaseUrl: 'https://github.example.com/api/v3', detectUrls: ['github.example.com'] },
gitlab: { apiBaseUrl: 'gitlab.example.com', detectUrls: [] },
gitea: { apiBaseUrl: '', detectUrls: ['gitea.example.com'] },
},
};
expect(helpers.sanitizeSettingsUpdate(payload)).toEqual({
gitProviders: {
github: { apiBaseUrl: 'https://github.example.com/api/v3', detectUrls: ['github.example.com'] },
gitlab: { apiBaseUrl: 'https://gitlab.example.com' },
gitea: { detectUrls: ['gitea.example.com'] },
},
});
});
it('drops malformed gitProviders payloads entirely', () => {
const helpers = createTestHelpersWithRealSanitizers();
expect(helpers.sanitizeSettingsUpdate({ gitProviders: 'not-an-object' })).toEqual({});
expect(helpers.sanitizeSettingsUpdate({ gitProviders: [] })).toEqual({});
expect(helpers.sanitizeSettingsUpdate({ gitProviders: null })).toEqual({});
expect(helpers.sanitizeSettingsUpdate({ gitProviders: { unknown: { apiBaseUrl: 'https://x.example.com' } } })).toEqual({});
expect(helpers.sanitizeSettingsUpdate({ gitProviders: { github: { apiBaseUrl: ' ' } } })).toEqual({});
expect(helpers.sanitizeSettingsUpdate({ gitProviders: { github: { detectUrls: 'github.example.com' } } })).toEqual({});
});
it('normalizes gitProviders apiBaseUrl scheme and strips trailing slashes', () => {
const helpers = createTestHelpersWithRealSanitizers();
expect(helpers.sanitizeSettingsUpdate({
gitProviders: { github: { apiBaseUrl: 'github.example.com/api/v3/' } },
})).toEqual({
gitProviders: { github: { apiBaseUrl: 'https://github.example.com/api/v3' } },
});
});
});
describe('session retention settings persistence', () => {