Control de modo editor/admin produccion/local

This commit is contained in:
Jordan Diaz
2026-04-10 16:52:00 +00:00
parent 0a8756c308
commit 224ac2dad7
6 changed files with 55 additions and 10 deletions

View File

@@ -18,6 +18,13 @@ import { fetchProjectInfo } from "./localClient.js";
const DEFAULT_ROLE = 'developer';
const FORGE_INTERNAL_URL = process.env.ACAI_FORGE_WEB_URL || "http://web:80";
const resolveEffectiveRole = (baseRole) => {
if (process.env.ACAI_ROLE_OVERRIDE) return process.env.ACAI_ROLE_OVERRIDE;
if (process.env.ACAI_MODE_OVERRIDE === "production") return "editor";
if (process.env.ACAI_MODE === "production") return "editor";
return baseRole || DEFAULT_ROLE;
};
// Session-based credentials storage (ephemeral, per-session)
export const sessionCredentials = new Map();
@@ -99,7 +106,7 @@ const readProjectAcaiFallback = () => {
tokenHash: data.tokenHash || process.env.ACAI_TOKEN_HASH || null,
mode,
profileName: "acai-file",
role: DEFAULT_ROLE,
role: resolveEffectiveRole(data.role),
};
} catch (error) {
console.error(`[Credentials] Failed to read .acai fallback: ${error.message}`);
@@ -136,7 +143,7 @@ const resolveLocalProjectFallback = async () => {
tokenHash: info.tokenHash || process.env.ACAI_TOKEN_HASH || null,
mode,
profileName: "project-info",
role: DEFAULT_ROLE,
role: resolveEffectiveRole(info.role),
};
}
} catch (error) {
@@ -279,7 +286,7 @@ export const getSessionCredentials = async (sessionId, inlineCredentials = null)
forge_host: process.env.ACAI_FORGE_HOST || null,
tokenHash: process.env.ACAI_TOKEN_HASH || null,
profileName: 'default',
role: 'developer', // Env fallback = local dev, full access
role: resolveEffectiveRole('developer'), // Env fallback = local dev, full access
};
};

View File

@@ -4,12 +4,17 @@ import { registerAcaiLineReplaceTool } from "./lineReplace.js";
import { registerAcaiDeleteTool } from "./delete.js";
import { registerAcaiGlobTool } from "./glob.js";
import { registerAcaiGrepTool } from "./grep.js";
import { canEditCode } from "../helpers/roleCheck.js";
export function registerFileTools(server) {
// Lectura: siempre disponible
registerAcaiViewTool(server);
registerAcaiGlobTool(server);
registerAcaiGrepTool(server);
registerAcaiWriteTool(server);
registerAcaiLineReplaceTool(server);
registerAcaiDeleteTool(server);
// Escritura: solo si el rol puede editar codigo
if (canEditCode()) {
registerAcaiWriteTool(server);
registerAcaiLineReplaceTool(server);
registerAcaiDeleteTool(server);
}
}

View File

@@ -0,0 +1,24 @@
/**
* Helper central para determinar el rol efectivo del MCP y bloquear tools
* peligrosas cuando el user es "editor".
*
* El rol se recibe principalmente via env var ACAI_ROLE_OVERRIDE inyectada
* por el backend Python (agentic.py y cronjobs.py). Hay autoderivacion
* defensiva en caso de que alguien lance el MCP sin el override:
* - Si ACAI_MODE(_OVERRIDE) = "production" → rol editor por defecto.
* - Si no → rol developer.
*/
export function getEffectiveRole() {
if (process.env.ACAI_ROLE_OVERRIDE) return process.env.ACAI_ROLE_OVERRIDE;
if (process.env.ACAI_MODE_OVERRIDE === "production") return "editor";
if (process.env.ACAI_MODE === "production") return "editor";
return "developer";
}
/**
* True si el rol efectivo puede editar archivos de codigo.
* Los roles permitidos son todo lo que NO sea "editor".
*/
export function canEditCode() {
return getEffectiveRole() !== "editor";
}

View File

@@ -1,9 +1,12 @@
import { registerCheckModuleTool } from './check.js';
import { registerCheckModuleUsageTool } from './checkUsage.js';
import { registerCompileModuleTool } from './compile.js';
import { canEditCode } from '../helpers/roleCheck.js';
export function registerModuleTools(server) {
registerCheckModuleTool(server);
registerCheckModuleUsageTool(server);
registerCompileModuleTool(server);
if (canEditCode()) {
registerCompileModuleTool(server);
}
}

View File

@@ -1,7 +1,10 @@
import { registerSaveProjectStylesTool } from "./saveStyles.js";
import { registerGetWebUrlTool } from "./getWebUrl.js";
import { canEditCode } from "../helpers/roleCheck.js";
export function registerProjectTools(server) {
registerSaveProjectStylesTool(server);
registerGetWebUrlTool(server);
registerGetWebUrlTool(server); // siempre
if (canEditCode()) {
registerSaveProjectStylesTool(server);
}
}

View File

@@ -1,5 +1,8 @@
import { registerRecoverGitTools } from './rollback.js';
import { canEditCode } from '../helpers/roleCheck.js';
export function registerRemoteGitTools(server) {
registerRecoverGitTools(server);
if (canEditCode()) {
registerRecoverGitTools(server);
}
}