feat(FN-2496): add overlap ignore paths support to scheduler settings

- Add overlap-ignore path validation and typed settings support in core schema
- Apply overlap ignore paths in scheduler overlap detection with dedicated engine tests
- Add Settings modal UI and routes handling for overlap ignore paths including path-picker feedback fixes
- Document overlap ignore paths in storage/settings docs and include a changeset for @runfusion/fusion
This commit is contained in:
Fusion
2026-04-25 15:48:36 -07:00
committed by gsxdsm
parent 792532f726
commit c57d11a659
11 changed files with 570 additions and 7 deletions

View File

@@ -505,6 +505,36 @@ function validateModelPresets(value: unknown): ModelPreset[] | undefined {
});
}
function sanitizeOverlapIgnorePaths(value: unknown): string[] | undefined {
if (value === undefined || value === null) return undefined;
if (!Array.isArray(value)) {
throw badRequest("overlapIgnorePaths must be an array of project-relative paths");
}
const normalized = value.map((entry, index) => {
if (typeof entry !== "string") {
throw badRequest(`overlapIgnorePaths[${index}] must be a string`);
}
const trimmed = entry.trim().replaceAll("\\", "/");
if (!trimmed) {
throw badRequest(`overlapIgnorePaths[${index}] cannot be empty`);
}
if (isAbsolute(trimmed) || /^[a-zA-Z]:\//.test(trimmed)) {
throw badRequest(`overlapIgnorePaths[${index}] must be a project-relative path`);
}
if (/^\.{1,2}(\/|$)/.test(trimmed) || /(^|\/)\.\.(\/|$)/.test(trimmed)) {
throw badRequest(`overlapIgnorePaths[${index}] cannot include '..' traversal`);
}
return trimmed;
});
return [...new Set(normalized)];
}
// ── Run-Audit Timeline Types & Helpers ─────────────────────────────────────
/** Valid domain filters for run-audit queries. */
@@ -2671,6 +2701,9 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
if (Object.prototype.hasOwnProperty.call(clientSettings, "modelPresets")) {
clientSettings.modelPresets = validateModelPresets(clientSettings.modelPresets);
}
if (Object.prototype.hasOwnProperty.call(clientSettings, "overlapIgnorePaths")) {
clientSettings.overlapIgnorePaths = sanitizeOverlapIgnorePaths(clientSettings.overlapIgnorePaths);
}
// Validate backup settings if provided
if (clientSettings.autoBackupSchedule !== undefined && !validateBackupSchedule(clientSettings.autoBackupSchedule)) {