feat(FN-3507): block dispatch when project lacks node mapping
Adds validation to block task dispatch when no project-node mapping exists (FN-3507), including a read helper in CentralCore and a new `node-dispatch-validation` module integrated into the scheduler and in-process runtime, with test coverage across routing and validation scenarios. Fusion-Task-Id: FN-3507
This commit is contained in:
@@ -804,6 +804,29 @@ describe("CentralCore", () => {
|
||||
await expect(central.getProjectNodePathMapping(project.id, nodeA.id)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return exact mapped path via getProjectNodePath and undefined for unmapped pairs", async () => {
|
||||
const projectPath = join(tempDir, "mapping-read-project");
|
||||
mkdirSync(projectPath);
|
||||
projectPaths.push(projectPath);
|
||||
|
||||
const project = await central.registerProject({
|
||||
name: "Mapping Read Project",
|
||||
path: projectPath,
|
||||
});
|
||||
const mappedNode = await central.registerNode({ name: "mapping-read-node", type: "local" });
|
||||
const otherNode = await central.registerNode({ name: "mapping-read-node-other", type: "local" });
|
||||
|
||||
await central.upsertProjectNodePathMapping({
|
||||
projectId: project.id,
|
||||
nodeId: mappedNode.id,
|
||||
path: "/mapped/node/path",
|
||||
});
|
||||
|
||||
await expect(central.getProjectNodePath(project.id, mappedNode.id)).resolves.toBe("/mapped/node/path");
|
||||
await expect(central.getProjectNodePath(project.id, otherNode.id)).resolves.toBeUndefined();
|
||||
await expect(central.getProjectNodePath("proj_missing", mappedNode.id)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("should validate project and node existence for mapping APIs", async () => {
|
||||
const node = await central.registerNode({ name: "mapping-validation-node", type: "local" });
|
||||
|
||||
|
||||
@@ -1769,6 +1769,16 @@ export class CentralCore extends EventEmitter<CentralCoreEvents> {
|
||||
return row ? this.rowToProjectNodePathMapping(row) : undefined;
|
||||
}
|
||||
|
||||
async getProjectNodePath(projectId: string, nodeId: string): Promise<string | undefined> {
|
||||
this.ensureInitialized();
|
||||
|
||||
const row = this.db!
|
||||
.prepare("SELECT path FROM projectNodePathMappings WHERE projectId = ? AND nodeId = ?")
|
||||
.get(projectId, nodeId) as { path: string } | undefined;
|
||||
|
||||
return row?.path;
|
||||
}
|
||||
|
||||
async listProjectNodePathMappings(filters?: {
|
||||
projectId?: string;
|
||||
nodeId?: string;
|
||||
|
||||
Reference in New Issue
Block a user